在我的 SQL Server 2000 数据库中,我有一个时间戳(在函数中而不是在数据类型中)类型列 DATETIME 命名的 lastTouched 设置 getdate() 作为其默认值/绑定。

我正在使用 Netbeans 6.5 生成的 JPA 实体类,并将其包含在我的代码中

@Basic(optional = false)
@Column(name = "LastTouched")
@Temporal(TemporalType.TIMESTAMP)
private Date lastTouched;

然而,当我尝试将对象放入数据库时​​,我得到了,

javax.persistence.PersistenceException: org.hibernate.PropertyValueException: not-null property references a null or transient value: com.generic.Stuff.lastTouched

我尝试过设置 @Basic(optional = true), ,但这会引发异常,表示数据库不允许 null 的值 TIMESTAMP 列,它不是设计的。

ERROR JDBCExceptionReporter - Cannot insert the value NULL into column 'LastTouched', table 'DatabaseName.dbo.Stuff'; column does not allow nulls. INSERT fails.

我之前让它在纯 Hibernate 中工作,但我感觉切换到 JPA 并且不知道如何告诉它该列应该在数据库端生成。请注意,我仍然使用 Hibernate 作为我的 JPA 持久层。

有帮助吗?

解决方案

我通过将代码更改为解决了该问题

@Basic(optional = false)
@Column(name = "LastTouched", insertable = false, updatable = false)
@Temporal(TemporalType.TIMESTAMP)
private Date lastTouched;

因此在生成 SQL 插入时会忽略时间戳列。不确定这是否是解决此问题的最佳方法。欢迎反馈。

其他提示

我意识到这有点晚了,但我已经成功地用注释时间戳列

@Column(name="timestamp", columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP")

这也应该与 CURRENT_DATECURRENT_TIME. 。我正在将 JPA/Hibernate 与 Oracle 一起使用,所以 YMMV。

@Column(nullable = false, updatable = false)
@CreationTimestamp
private Date created_at;

这对我有用。更多信息

对于我只关心最后一次修改行的情况,我使用 JPA2.0 和 MySQL 5.5.10 可以很好地工作。MySQL 将在第一次插入时以及每次对该行调用 UPDATE 时创建时间戳。(笔记:如果我关心更新是否实际进行了更改,这将是有问题的)。

本例中的“timestamp”列就像“last-touched”列。x`

下面的代码使用单独的列“版本”进行乐观锁定。

private long version;
private Date timeStamp

@Version
public long getVersion() {
    return version;
}

public void setVersion(long version) {
    this.version = version;
}

// columnDefinition could simply be = "TIMESTAMP", as the other settings are the MySQL default
@Column(name="timeStamp", columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
@Temporal(TemporalType.TIMESTAMP)
public Date getTimeStamp() {
    return timeStamp;
}

public void setTimeStamp(Date timeStamp) {
    this.timeStamp = timeStamp;
}

(笔记:@Version 不适用于 MySQL“DATETIME”列,其中实体类中的属性类型为“Date”。这是因为 Date 生成的值精确到毫秒,但是 MySQL 没有存储毫秒,因此当它对数据库中的内容和“附加”实体进行比较时,它认为它们具有不同的版本号)

来自 MySQL 手册中有关 TIMESTAMP 的内容 :

With neither DEFAULT nor ON UPDATE clauses, it is the same as DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP.

我不认为每个数据库都有自动更新时间戳(例如Postgres)。因此,我决定在代码中的所有位置手动更新此字段。这适用于每个数据库:

thingy.setLastTouched(new Date());
HibernateUtil.save(thingy);

使用触发器是有原因的,但对于大多数项目来说,这不是其中之一。触发器可以让您更深入地了解特定的数据库实现。

MySQL 5.6.28(Ubuntu 15.10,OpenJDK 64位1.8.0_66)似乎非常宽容,不需要任何超出的东西

@Column(name="LastTouched")

MySQL 5.7.9(CentOS 6、OpenJDK 64 位 1.8.0_72)仅适用于

@Column(name="LastTouched", insertable=false, updatable=false)

不是:

FAILED: removing @Temporal
FAILED: @Column(name="LastTouched", nullable=true)
FAILED: @Column(name="LastTouched", columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")

我的其他系统信息(在两种环境中相同)

  • 休眠实体管理器 5.0.2
  • 休眠验证器 5.2.2
  • mysql-连接器-java 5.1.38
@Column(name = "LastTouched", insertable = false, updatable = false, columnDefinition = "TIMESTAMP default getdate()")
@Temporal(TemporalType.TIMESTAMP)
private Date LastTouched;`enter code here`
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top