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 添加我們的 EntityListeners
如果您真的需要,那麼您可以將 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;
}