5.1 Masa perubahan data
Apabila anda menyimpan pelbagai rekod dalam pangkalan data selama bertahun-tahun, dua soalan sering timbul:
- Bilakah entri ini ditambahkan pada pangkalan data?
- Bilakah kali terakhir entri ini ditukar?
Ini adalah tugas yang kerap sehingga dua lajur ditambahkan pada hampir setiap jadual dalam pangkalan data:
- masa_dicipta
- masa_kemas kini
Yang pertama menyimpan tarikh dan masa rekod dibuat, dan yang kedua menyimpan tarikh dan masa ia terakhir diubah suai. Dan setiap kelas Entiti mempunyai medan:
@Entity
@Table(name = "entities")
public class Entity {
...
@Column(name="created_time")
private Date created;
@Column(name="updated_time")
private Date updated;
}
Hibernate boleh melakukan semua kerja mengawal apabila objek dalam pangkalan data dikemas kini dengan dua anotasi @CreationTimestamp
dan @UpdateTimestamp
.
Contoh:
@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;
}
Lajur yang ditandakan dengan anotasi ini akan sentiasa menyimpan masa yang betul apabila objek itu dibuat dan bila kali terakhir ia diubah suai.
5.2 anotasi @PrePersist
Jika anda memerlukan beberapa skrip yang lebih kompleks untuk mengawal masa sesuatu objek, maka Hibernate mempunyai anotasi untuk kes ini juga. Mereka boleh menandakan kaedah kelas, dan Hibernate akan memanggil kaedah ini apabila ia menyimpan objek ke pangkalan data. Terdapat 7 anotasi sedemikian secara keseluruhan:
@PrePersist | Dipanggil sebelum objek disimpan ke pangkalan data. (Sisipan SQL) |
@PostPersist | Dipanggil serta-merta selepas objek disimpan ke pangkalan data. (Sisipan SQL) |
@PreRemove | Dipanggil sebelum memadam objek dalam pangkalan data. |
@PostRemove | Dipanggil selepas objek telah dipadamkan daripada pangkalan data. |
@PreUpdate | Dipanggil sebelum mengemas kini (SQL UPDATE) objek dalam pangkalan data. |
@PostUpdate | Dipanggil selepas kemas kini (SQL UPDATE) objek dalam pangkalan data. |
@PostLoad | Dipanggil selepas objek telah dimuatkan daripada pangkalan data. |
Mari tulis contoh di mana kita memberitahu kelas masa yang betul untuk mencipta dan mengemas kini objeknya:
@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();
}
}
Jika Hibernate menyimpan objek buat kali pertama, maka ia akan memanggil kaedah beranotasi dengan @PrePersist
. Jika ia mengemas kini objek sedia ada dalam pangkalan data, ia akan memanggil kaedah yang ditandakan dengan anotasi @PreUpdate
.
5.3 Menambah EntityListeners kami
Jika anda benar-benar perlu, maka anda boleh memisahkan kaedah yang dipanggil Hibernate daripada objek yang ia memanggilnya. Spesifikasi JPA membolehkan anda mengisytiharkan kelas pendengar yang akan dipanggil pada masa tertentu apabila memproses objek Entiti.
Jika anda mempunyai banyak objek Entiti yang serupa, maka anda boleh memindahkan sebahagian daripadanya ke dalam kelas asas dan menambah Pendengar yang akan mengawal tingkah laku mereka. Contoh:
@MappedSuperclass
public abstract class BaseEntity {
private Timestamp createdOn;
private Timestamp updatedOn;
}
@Entity
public class User extends BaseEntity {
@Id
private Long id;
private String name;
}
Kemudian untuk kelas BaseEntity, anda boleh membuat kelas pendengar khas:
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) );
}
}
Dan anda boleh menyambungkan kelas Pengguna dan pendengarnya menggunakan beberapa anotasi:
@Entity
@EntityListeners(class= TimeEntityListener.class)
public class User extends BaseEntity {
@Id
private Long id;
private String name;
}