5.1 数据变化时间
当您在数据库中存储各种记录多年时,经常会出现两个问题:
- 这个条目是什么时候添加到数据库中的?
- 此条目上次更改的时间是什么时候?
这些是非常频繁的任务,以至于数据库中几乎每个表都添加了两列:
- 创建时间
- 更新时间
第一个存储记录创建的日期和时间,第二个存储上次修改的日期和时间。每个实体类都有字段:
@Entity
@Table(name = "entities")
public class Entity {
...
@Column(name="created_time")
private Date created;
@Column(name="updated_time")
private Date updated;
}
Hibernate 可以完成所有的控制工作,当数据库中的对象更新时有两个注解@CreationTimestamp
和@UpdateTimestamp
。
例子:
@Entity
@Table(name = "entities")
public class Entity {
...
@CreationTimestamp
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "create_date")
private Date createDate;
@UpdateTimestamp
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "modify_date")
private Date modifyDate;
}
标有这些注释的列将始终存储正确的对象创建时间和最后修改时间。
5.2 @PrePersist 注解
如果你需要一些更复杂的脚本来控制对象的时间,那么 Hibernate 也有针对这种情况的注释。它们可以标记类方法,Hibernate 将对象保存到数据库时会调用这些方法。总共有7个这样的注解:
@PrePersist | 在将对象保存到数据库之前调用。(SQL 插入) |
@PostPersist | 在对象保存到数据库后立即调用。(SQL 插入) |
@PreRemove | 在删除数据库中的对象之前调用。 |
@PostRemove | 从数据库中删除对象后调用。 |
@预更新 | 在更新 (SQL UPDATE) 数据库中的对象之前调用。 |
@PostUpdate | 在数据库中的对象更新 (SQL UPDATE) 之后调用。 |
@postload | 从数据库加载对象后调用。 |
让我们写一个例子,我们告诉一个类正确的时间来创建和更新它的对象:
@Entity
@Table(name = "entities")
public class Entity {
...
@Column(name="created_time")
private Date created;
@Column(name="updated_time")
private Date updated;
@PrePersist
protected void onCreate() {
created = new Date();
}
@PreUpdate
protected void onUpdate() {
updated = new Date();
}
}
如果 Hibernate 第一次保存该对象,那么它会调用注解为@PrePersist
. 如果它更新数据库中的现有对象,它将调用标有注释的方法@PreUpdate
。
5.3 添加我们的 EntityListener
如果您真的需要,那么您可以将 Hibernate 调用的方法与其调用它们的对象分开。JPA 规范允许您声明在处理实体对象时将在特定时间调用的侦听器类。
如果您有很多类似的 Entity 对象,那么您可以将其中一些移到基类中并添加一个 Listener 来控制它们的行为。例子:
@MappedSuperclass
public abstract class BaseEntity {
private Timestamp createdOn;
private Timestamp updatedOn;
}
@Entity
public class User extends BaseEntity {
@Id
private Long id;
private String name;
}
然后对于 BaseEntity 类,您可以创建一个特殊的侦听器类:
public class TimeEntityListener {
public void onPersist(Object entity) {
if (entity instanceof BaseEntity) {
BaseEntity baseEntity = (BaseEntity) entity;
baseEntity.createdOn = now();
}
}
public void onUpdate(Object entity) {
if (entity instanceof BaseEntity) {
BaseEntity baseEntity = (BaseEntity) entity;
baseEntity.updatedOn = now();
}
}
private Timestamp now() {
return Timestamp.from(LocalDateTime.now().toInstant(ZoneOffset.UTC) );
}
}
您可以使用几个注释连接 User 类及其侦听器:
@Entity
@EntityListeners(class= TimeEntityListener.class)
public class User extends BaseEntity {
@Id
private Long id;
private String name;
}