ON UPDATE CURRENT_TIMESTAMP和JPA

时间:2011-07-06 13:55:57

标签: sql hibernate jpa spring-data

我有一个带字段的实体

@Temporal(TemporalType.TIMESTAMP)
@Column(name = "edit_timestamp", 
        columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
private Date editTimestamp;

@Version
@Column(name = "edit_count")
private short editCount;

private String text;

当我尝试使用Spring-Data-JPA进行更新时,我发现edit_count已经增加,但edit_timestamp仍然保持不变。如果我手动调用SQL

UPDATE post SET TEXT='456' WHERE post_id=1;

edit_timestamp已更新。如果我添加

@PreUpdate
protected void onUpdate() {
    editTimestamp = new Date();
}

它没有问题。我的问题是为什么w / o @PreUpdate没有更新edit_timestamp?

3 个答案:

答案 0 :(得分:8)

这是一个老问题,但我想如果其他人发现它有用,我会提出答案。 我认为您需要更改列注释以包含updatable = false。这将导致edit_timestamp列不显示在更新sql中,因此JPA提供程序将不包含该字段的当前值,这是导致它覆盖默认值的原因。

@Temporal(TemporalType.TIMESTAMP)
@Column(name = "edit_timestamp", 
        updatable = false
        columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
private Date editTimestamp;

答案 1 :(得分:0)

因为在你的初始注释集中,所有你告诉它的关于edit_timestamp列的是它是一个时间戳; JPA不知道它需要更新它。我猜测当你手动执行SQL语句时,你会有一些更新后的触发器,它会为你改变这些字段 - 但是当你更新它时,它会被来自持久化实体的数据覆盖。 /> 如果您不需要“已编辑”的计数/时间戳,请尝试从实体中删除它们,看看是否有效。否则,你有一个可行的解决方案。

答案 2 :(得分:0)

您可以在实体中将变量标记为更新或创建时间戳。在以下示例中,您可以看到如何使用休眠注释轻松完成此操作:

@UpdateTimestamp
private LocalDateTime editTimestamp;

@CreationTimestamp
private LocalDateTime creationTimestamp;

仅供参考并确保没有混淆,我将以下包导入用于相应的数据类型和注释:

import org.hibernate.annotations.CreationTimestamp
import org.hibernate.annotations.UpdateTimestamp
import java.time.LocalDateTime