JPA中的最后更新时间戳

14

我正在尝试使用JPA(具体来说是Eclipselink)。下面的实体应该有一个时间戳,以反映该实体上次更新的时间。

有哪些策略可以使JPA在每次更改此实体时自动更新该时间戳?

如果我还想要一个“创建”时间戳,只在首次持久化实体时设置,永远不允许再次更改,我该怎么做?

 @Entity
 public class Item implements Serializable {
     private static final long serialVersionUID = 1L;
     private Integer id;
     private String note;


    public Item () {
    }


    @Id
    @GeneratedValue(strategy=SEQUENCE)
    @Column(unique=true, nullable=false)
    public Integer getId() {
        return this.id;
    }

    public void setId(Integer id) {
        this.id = id;
    }


    @Column(length=255)
    @Column(nullable=false)
    public String getNote() {
        return this.note;
    }

    public void setNote(String note) {
        this.note = note;
    }

    @Column(nullable=false)
    public Timestamp getUpdated() {
        return this.updated;
    }

    public void setUpdated(Timestamp updated) {
        this.updated = updated;
    }


}
4个回答

19

使用@PrePersist@PreUpdate注解并编写自己的事件监听器。

详细信息请参见此答案。它被标记为Hibernate,但适用于任何JPA提供程序。


2

如果您正在使用MySQL,我认为您可以执行以下操作来禁用时间戳更新实体:

@Column(name = "lastUpdate", updatable= false, insertable=false)
@Temporal(TemporalType.TIMESTAMP)
private Date lastUpdate;

对于Oracle,您需要使用上面解释的@PreUpdate注释从实体设置时间戳。


这是错误的原因有很多:(1) 上述假设您手动更新时间戳,因此设置“可更新”是无意义的;(2) 因此,上述代码将无法在没有@PreUpdate / @PrePersist事件侦听器的情况下工作;(3) 如果您希望数据库生成您的时间戳(您似乎在暗示),则必须将属性标记为已生成,而这不是JPA标准;(4) 最后,MySQL不允许您在同一表中拥有2个自动更新的时间戳。 - ChssPly76
关于mysql,您可以创建一个或多个触发器来更新任意数量的列,例如时间戳 - 在表中不限制只能有1个自动更新的时间戳。 - nos
在MySql中,您还可以使用2个时间戳创建表,并在插入记录时在两个字段上都插入NULL。创建表ts( last_updated_ts TIMESTAMP, created_ts TIMESTAMP, name varchar(5) );insert into ts(last_updated_ts,created_ts,name)value(null,null,'test');无论客户端如何访问数据库,肯定触发器或注释更好。 - surajz

1
在实体类中。
@Column
@UpdateTimestamp
private Timestamp updatedOn

@Column
@CreationTimestamp
private Timestamp createdOn

当实体发生任何更改时,它将自动更新

支持的属性类型

java.time.LocalDate (since Hibernate 5.2.3)
java.time.LocalDateTime (since Hibernate 5.2.3)
java.util.Date
java.util.Calendar
java.sql.Date
java.sql.Time
java.sql.Timestamp

例子:

@Entity
public class MyEntity {
 
    @Id
    @GeneratedValue
    private Long id;
 
    @CreationTimestamp
    private Timestamp createdOn;
 
    @UpdateTimestamp
    private Timestamp updatedOn;
 
}

1

实际上,surajz的答案是有效的。考虑一种情况,您正在跟踪2个时间戳。您想通过实体手动更新它们。您需要将其中一个设置为updateble=false(当记录更新时不希望更新的那个),并使另一个自由更新。

这对我有用。


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