【问题标题】:Updatable false behvior incosistent可更新的错误行为不一致
【发布时间】:2010-05-06 10:11:46
【问题描述】:

每当更新记录时,我需要由 SYSDATE 更新 LastUpdatedDttm。但是下面的注释不能按预期工作。 SYSDATE 仅插入一次,不会为后续更新而更新。另外,lastUpdDTTM 不是 hibernate 生成的 sql 的一部分。

@Generated(GenerationTime.ALWAYS)
@Column(name="LAST_UPDATED_DTTM",insertable=false,updatable=true, columnDefinition ="timestamp default SYSDATE")
private Date lastUpdDTTM;

@Generated(GenerationTime.ALWAYS)
@Column(name="CREATED_DTTM", insertable=false, updatable=false)
private Date createdDTTM;

【问题讨论】:

  • 您使用的是哪种 JPA 实现?它可能会有所帮助。

标签: java hibernate orm jpa


【解决方案1】:

(...) SYSDATE 仅插入一次,不会针对后续更新进行更新。

首先,让我明确一点:Generated 表示该字段是由数据库生成,并且 Hibernate 需要在插入/更新后读取它以更新实体。在列定义中使用 default SYSDATE 对于 INSERT 效果很好,但对于 UPDATE,您需要一个触发器。

另外,lastUpdDTTM 不是 hibernate 生成的 sql 的一部分。

好吧,您告诉 Hibernate 该字段是由数据库生成的 ALWAYS,所以我并不惊讶 Hibernate 没有将它包含在生成的 SQL 中(实际上,我相信这与 udpatable = true 有某种冲突,我希望 Hibernate 会抱怨它)。

无论如何,正如我所说,更新此字段的不是 Hibernate,而是数据库,您需要一个触发器,Hibernate 只会在更新后刷新实体以获取新值。


另一种方法是使用回调注释,例如最后更新日期:

@PreUpdate
protected void updateDates() {
    lastUpdDTTM = new Date();
}

为了更好的一致性,您甚至可以使用与@PrePersit 相同的方法来创建日期:

@PrePersist
@PreUpdate
protected void updateDates() {
    Date now = new Date();
    if (createdDTTM == null) {
        createdDTTM = new Date(now.getTime());
    }
    lastUpdDTTM = now;
}

【讨论】:

  • 再次感谢。但我真的不想使用触发器。没有其他解决方案吗?
  • 我希望我可以使用回调。它必须数据库服务器日期时间。这种方法会给我网络服务器当前时间。
  • @jpanewbie 确实。最后一个想法:也使用default SYSDATE 作为更新日期,并在@PreUpdate 方法中将更新日期设置为null
  • LastUpDttm col 不是 NULL 默认 Sysdate 在 DB 级别。 @Generated(GenerationTime.ALWAYS) @Column(name="LAST_UPDATED_DTTM", insertable=false, updatable=false, columnDefinition = "timestamp default SYSDATE") private Date lastUpdDTTM;即使我在 @Preupdate 方法中将字段设置为 null,它也会被忽略。
猜你喜欢
  • 1970-01-01
  • 2014-06-15
  • 1970-01-01
  • 2012-06-16
  • 1970-01-01
  • 1970-01-01
  • 2013-06-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多