如何在使用Hibernate保存数据时使用数据库端的默认值?

54
我在数据库中有一个默认值为 sysdate 的列。我想找到一种方法,在应用程序端不提供任何对应属性的情况下插入该默认值。顺便说一下,我正在使用基于注解的配置。
有什么建议吗?
4个回答

119
当插入数据时,即使将日期列定义为default SYSDATE dbms-side,它仍会获得null值的原因是,如果查询中给该列赋了值,则该列的默认值default将不起作用。这意味着即使给出null,它也不应出现在INSERT INTO语句中。
如果要在DBMS端使用default SYSDATE,则应配置@Columninsertable=false,以便从SQL INSERT中排除该列。
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "myDate", insertable=false)
private Date myDate;

请注意,这种方法总是会忽略在创建实体时应用程序提供的属性值。如果您真的想有时提供日期,也许应该考虑使用DB触发器来设置值,而不是使用默认值。
DBMS的default SYSDATE定义有一个替代方案。您可以使用@PrePersist@PreUpdate注释,在保存/更新之前为属性分配当前日期,仅当尚未分配日期时才执行此操作:
@PrePersist
protected void onCreate() {
    if (myDate == null) { myDate = new Date(); }
}

这个相关问题提供了不同的方法:使用Hibernate和MySQL创建时间戳和最后更新时间戳


1
谢谢你提供如此详细的解释,Xavi。这超出了我的期望,而且确实有效! - BruceCui
1
@Doug 很高兴知道你解决了这个问题,除了避免在分配DB端值后返回DB检索值之外,我不明白 @Generated 如何帮助到你。你尝试在 @Column 定义中使用 insertable=false 吗?正如上面的评论所提到的那样,只要继续使用Hibernate,@UpdateTimestamp 也是一个非常有效的方法。 - Xavi López
是的,我也尝试了 insertable=false,但它没有起作用。在 .save() 后,modified_at 列仍然返回为 null,不知道为什么... - Doug
@Doug 如果这实际上是一个UPDATE而不是一个INSERT,那么updatable=false可能会有所帮助。无论如何,@UpdateTimestamp已经是一个很好的解决方案了,如果可能的话,我更喜欢在自己的代码中设置默认值,而不是在DBMS端设置。 - Xavi López
1
@Doug 多种原因 - 考虑到默认值大多数情况下遵循应用程序逻辑(例如,您可以在数据库端默认 creation_date,但不能默认 creation_user),我宁愿将它们放在一个地方(当然尽可能的情况下),特别是我知道我有控制权的地方,并且不会引起任何副作用,而不是分散在不同的层中。 - Xavi López
显示剩余6条评论

21

如果你正在使用Hibernate,那么你可以直接使用@CreationTimestamp来插入默认日期。

@CreationTimestamp
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "create_date")
private Date createDate;

如果必要的话,使用@UpdateTimestamp更新值

@UpdateTimestamp
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "modify_date")
private Date modifyDate;

这对我很有帮助 - 我已经寻找这个答案一段时间了!谢谢,@rajadilipkolli :) - Custard
这是对我有效的解决方案,第一个答案没有起作用。感谢@rajadilipkolli。 - Doug
这个可以工作,但是使用的是系统时间,有没有办法使用数据库时间?就像HQL的CURRENT_TIMESTAMP()一样?编辑:不更改数据库模式? - gagarwa

0
在你的实体上加上@DynamicInsert注解,那么空值将被省略,而默认值将被采用。 来源:Hibernate 5.5文档

0

或者你可以直接初始化POJO的属性,例如:

//java code property declaration

private String surname = "default";

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接