1. ควรใช้คอลัมน์ฐานข้อมูลประเภทใด
คำถามแรกของคุณคือ:
ชนิดข้อมูลใดที่คุณจะใช้ในฐานข้อมูล (สมมติว่า MySQL อาจเป็นในเขตเวลาอื่นที่ JVM) ชนิดข้อมูลจะตระหนักถึงเขตเวลาหรือไม่
ใน MySQL TIMESTAMP
ชนิดคอลัมน์จะเปลี่ยนจากเขตเวลาท้องถิ่นของไดรเวอร์ JDBC ไปเป็นเขตเวลาของฐานข้อมูล แต่สามารถเก็บบันทึกเวลาได้สูงสุด'2038-01-19 03:14:07.999999
เท่านั้นดังนั้นจึงไม่ใช่ตัวเลือกที่ดีที่สุดสำหรับอนาคต
ดังนั้นควรใช้DATETIME
แทนดีกว่าซึ่งไม่มีข้อ จำกัด ขอบเขตนี้ อย่างไรก็ตามDATETIME
ไม่ทราบเขตเวลา ดังนั้นด้วยเหตุนี้จึงเป็นการดีที่สุดที่จะใช้ UTC ทางด้านฐานข้อมูลและใช้hibernate.jdbc.time_zone
คุณสมบัติ Hibernate
สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับhibernate.jdbc.time_zone
การตั้งค่าให้ตรวจสอบบทความนี้
2. คุณควรใช้ประเภททรัพย์สินประเภทใด
คำถามที่สองของคุณคือ:
ชนิดข้อมูลใดที่คุณจะใช้ใน Java (วันที่, ปฏิทิน, ยาว, ... )
ในด้าน Java คุณสามารถใช้ Java LocalDateTime
8 นอกจากนี้คุณยังสามารถใช้แบบดั้งเดิมDate
แต่ประเภท Java 8 Date / Time ดีกว่าเนื่องจากไม่เปลี่ยนรูปและไม่ทำการเปลี่ยนเขตเวลาเป็นเขตเวลาท้องถิ่นเมื่อทำการบันทึก
สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับ Java 8 วันที่ / เวลาประเภทการสนับสนุนจาก Hibernate ตรวจสอบบทความนี้
ตอนนี้เราสามารถตอบคำถามนี้ได้:
คุณจะใช้คำอธิบายประกอบใดสำหรับการทำแผนที่ (เช่น@Temporal
)
หากคุณกำลังใช้LocalDateTime
หรือjava.sql.Timestamp
เพื่อแมปคุณสมบัติเอนทิตีการประทับเวลาดังนั้นคุณไม่จำเป็นต้องใช้@Temporal
เนื่องจาก HIbernate รู้อยู่แล้วว่าคุณสมบัตินี้จะถูกบันทึกเป็น JDBC Timestamp
เฉพาะในกรณีที่คุณใช้java.util.Date
งานคุณจะต้องระบุ@Temporal
คำอธิบายประกอบเช่นนี้:
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "created_on")
private Date createdOn;
แต่มันจะดีกว่ามากถ้าคุณแมปแบบนี้:
@Column(name = "created_on")
private LocalDateTime createdOn;
วิธีสร้างค่าคอลัมน์การตรวจสอบ
คำถามที่สามของคุณคือ:
คุณจะรับผิดชอบการตั้งค่าการประทับเวลา - ฐานข้อมูล, กรอบงาน ORM (ไฮเบอร์เนต) หรือโปรแกรมเมอร์โปรแกรม
คุณจะใช้คำอธิบายประกอบใดสำหรับการทำแผนที่ (เช่น @Temporal)
มีหลายวิธีที่คุณสามารถบรรลุเป้าหมายนี้ คุณสามารถอนุญาตให้ฐานข้อมูลทำ ..
สำหรับcreate_on
คอลัมน์คุณสามารถใช้DEFAULT
ข้อ จำกัด DDL เช่น:
ALTER TABLE post
ADD CONSTRAINT created_on_default
DEFAULT CURRENT_TIMESTAMP() FOR created_on;
สำหรับupdated_on
คอลัมน์คุณสามารถใช้ทริกเกอร์ DB เพื่อตั้งค่าคอลัมน์ด้วยCURRENT_TIMESTAMP()
ทุกครั้งที่มีการแก้ไขแถวที่กำหนด
หรือใช้ JPA หรือ Hibernate เพื่อตั้งค่าเหล่านั้น
สมมติว่าคุณมีตารางฐานข้อมูลต่อไปนี้:
และแต่ละตารางมีคอลัมน์เช่น:
created_by
created_on
updated_by
updated_on
การใช้ Hibernate @CreationTimestamp
และ@UpdateTimestamp
หมายเหตุประกอบ
Hibernate เสนอ@CreationTimestamp
และ@UpdateTimestamp
คำอธิบายประกอบที่สามารถใช้ในการแมปcreated_on
และupdated_on
คอลัมน์
คุณสามารถใช้@MappedSuperclass
เพื่อกำหนดคลาสพื้นฐานที่จะขยายโดยเอนทิตีทั้งหมด:
@MappedSuperclass
public class BaseEntity {
@Id
@GeneratedValue
private Long id;
@Column(name = "created_on")
@CreationTimestamp
private LocalDateTime createdOn;
@Column(name = "created_by")
private String createdBy;
@Column(name = "updated_on")
@UpdateTimestamp
private LocalDateTime updatedOn;
@Column(name = "updated_by")
private String updatedBy;
//Getters and setters omitted for brevity
}
และเอนทิตีทั้งหมดจะขยายตัวBaseEntity
เช่นนี้:
@Entity(name = "Post")
@Table(name = "post")
public class Post extend BaseEntity {
private String title;
@OneToMany(
mappedBy = "post",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();
@OneToOne(
mappedBy = "post",
cascade = CascadeType.ALL,
orphanRemoval = true,
fetch = FetchType.LAZY
)
private PostDetails details;
@ManyToMany
@JoinTable(
name = "post_tag",
joinColumns = @JoinColumn(
name = "post_id"
),
inverseJoinColumns = @JoinColumn(
name = "tag_id"
)
)
private List<Tag> tags = new ArrayList<>();
//Getters and setters omitted for brevity
}
สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับการใช้@MappedSuperclass
ตรวจสอบบทความนี้
อย่างไรก็ตามแม้ว่าจะมีการตั้งค่าคุณสมบัติcreatedOn
และupdateOn
โดยเฉพาะไฮเบอร์เนต@CreationTimestamp
และ@UpdateTimestamp
คำอธิบายประกอบcreatedBy
และยังupdatedBy
ต้องลงทะเบียนแอปพลิเคชันการโทรกลับตามที่แสดงในโซลูชัน JPA ต่อไปนี้
ใช้ JPA @EntityListeners
คุณสามารถสรุปคุณสมบัติการตรวจสอบในแบบฝังได้:
@Embeddable
public class Audit {
@Column(name = "created_on")
private LocalDateTime createdOn;
@Column(name = "created_by")
private String createdBy;
@Column(name = "updated_on")
private LocalDateTime updatedOn;
@Column(name = "updated_by")
private String updatedBy;
//Getters and setters omitted for brevity
}
และสร้างAuditListener
เพื่อตั้งค่าคุณสมบัติการตรวจสอบ:
public class AuditListener {
@PrePersist
public void setCreatedOn(Auditable auditable) {
Audit audit = auditable.getAudit();
if(audit == null) {
audit = new Audit();
auditable.setAudit(audit);
}
audit.setCreatedOn(LocalDateTime.now());
audit.setCreatedBy(LoggedUser.get());
}
@PreUpdate
public void setUpdatedOn(Auditable auditable) {
Audit audit = auditable.getAudit();
audit.setUpdatedOn(LocalDateTime.now());
audit.setUpdatedBy(LoggedUser.get());
}
}
หากต้องการลงทะเบียนAuditListener
คุณสามารถใช้@EntityListeners
คำอธิบายประกอบ JPA:
@Entity(name = "Post")
@Table(name = "post")
@EntityListeners(AuditListener.class)
public class Post implements Auditable {
@Id
private Long id;
@Embedded
private Audit audit;
private String title;
@OneToMany(
mappedBy = "post",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();
@OneToOne(
mappedBy = "post",
cascade = CascadeType.ALL,
orphanRemoval = true,
fetch = FetchType.LAZY
)
private PostDetails details;
@ManyToMany
@JoinTable(
name = "post_tag",
joinColumns = @JoinColumn(
name = "post_id"
),
inverseJoinColumns = @JoinColumn(
name = "tag_id"
)
)
private List<Tag> tags = new ArrayList<>();
//Getters and setters omitted for brevity
}
สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับการใช้คุณสมบัติการตรวจสอบกับ JPA @EntityListener
ตรวจสอบบทความนี้