在我的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插入时会忽略timestamp列。不确定这是否是解决此问题的最佳方式。欢迎反馈。
我意识到这有点晚了,但我已经成功地用时间戳列注释了
@Column(name="timestamp", columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
这也适用于CURRENT_DATE
和CURRENT_TIME
。我正在使用JPA / Hibernate和Oracle,所以YMMV。
@Column(nullable = false, updatable = false)
@CreationTimestamp
private Date created_at;
这对我有用。 more info
我使用JPA2.0和MySQL 5.5.10工作得很好,因为我只关心上次修改行的情况。 MySQL将在第一次插入时创建时间戳,并且每次在行上调用UPDATE时。 (注意:如果我关心UPDATE是否真的做了改变,这将是有问题的)。
此示例中的“timestamp”列类似于“last-touching”column.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”列,其中Entity类中的属性类型为“Date”。这是因为Date生成的值低至毫秒,但MySQL没有存储毫秒,所以当它对数据库中的内容和“附加”实体进行比较时,它认为它们有不同的版本号)
From the MySQL manual regarding 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-Bit 1.8.0_66)似乎非常宽容,不需要任何东西
@Column(name="LastTouched")
MySQL 5.7.9(CentOS 6,OpenJDK 64-Bit 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")
我的其他系统信息(两种环境都相同)