5.1 เวลาของการเปลี่ยนแปลงข้อมูล
เมื่อคุณจัดเก็บบันทึกต่างๆ ไว้ในฐานข้อมูลเป็นเวลาหลายปี มักจะเกิดคำถามสองข้อ:
- รายการนี้ถูกเพิ่มในฐานข้อมูลเมื่อใด
- รายการนี้เปลี่ยนแปลงครั้งล่าสุดเมื่อใด
สิ่งเหล่านี้เป็นงานที่พบบ่อยซึ่งมีการเพิ่มสองคอลัมน์ในเกือบทุกตารางในฐานข้อมูล:
- สร้างขึ้น_เวลา
- อัปเดต_เวลา
รายการแรกจัดเก็บวันที่และเวลาที่เรกคอร์ดถูกสร้างขึ้น และรายการที่สองจัดเก็บวันที่และเวลาที่แก้ไขครั้งล่าสุด และแต่ละคลาสเอนทิตีมีฟิลด์:
@Entity
@Table(name = "entities")
public class Entity {
...
@Column(name="created_time")
private Date created;
@Column(name="updated_time")
private Date updated;
}
ไฮเบอร์เนตสามารถทำงานทั้งหมดในการควบคุมเมื่อวัตถุในฐานข้อมูลได้รับการอัพเดตด้วยคำอธิบายประกอบสองรายการ@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 ก็มีคำอธิบายประกอบสำหรับกรณีนี้เช่นกัน พวกเขาสามารถทำเครื่องหมายวิธีการเรียนและไฮเบอร์เนตจะเรียกวิธีการเหล่านี้เมื่อบันทึกวัตถุลงในฐานข้อมูล มีทั้งหมด 7 ข้อเขียนดังกล่าว:
@PrePersist | เรียกใช้ก่อนที่จะบันทึกวัตถุลงในฐานข้อมูล (แทรก SQL) |
@PostPersist | เรียกใช้ทันทีหลังจากที่วัตถุถูกบันทึกลงในฐานข้อมูล (แทรก SQL) |
@ก่อนลบ | เรียกว่าก่อนที่จะลบวัตถุในฐานข้อมูล |
@โพสต์ลบ | เรียกใช้หลังจากที่วัตถุถูกลบออกจากฐานข้อมูล |
@PreUpdate | เรียกว่าก่อนที่จะอัปเดต (SQL UPDATE) วัตถุในฐานข้อมูล |
@โพสต์อัพเดท | เรียกว่าหลังจากการอัพเดต (SQL UPDATE) ของวัตถุในฐานข้อมูล |
@โพสต์โหลด | เรียกใช้หลังจากวัตถุถูกโหลดจากฐานข้อมูล |
ลองเขียนตัวอย่างที่เราบอกเวลาที่ถูกต้องในการสร้างและอัปเดตวัตถุในชั้นเรียน:
@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 คุณสามารถสร้างคลาส Listener พิเศษได้:
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;
}