1. Hangi veritabanı sütun türlerini kullanmalısınız?
İlk sorunuz:
Veritabanında hangi veri türlerini kullanırsınız (MySQL varsayalım, muhtemelen JVM'den farklı bir saat diliminde)? Veri türleri saat diliminde farkında olacak mı?
MySQL'de, TIMESTAMPsütun türü JDBC sürücüsü yerel saat diliminden veritabanı saat dilimine geçer, ancak yalnızca zaman damgalarını depolayabilir'2038-01-19 03:14:07.999999 , bu nedenle gelecek için en iyi seçim değildir.
Bu nedenle, DATETIMEbunun üst sınır sınırlaması olmayan daha iyi kullanım . Ancak, DATETIMEsaat dilimi farkında değildir. Bu nedenle, veritabanı tarafında UTC kullanmak ve hibernate.jdbc.time_zoneHibernate özelliğini kullanmak en iyisidir .
Ayarla ilgili daha fazla ayrıntı için bu makaleyehibernate.jdbc.time_zone göz atın .
2. Hangi varlık özelliği türünü kullanmalısınız?
İkinci sorunuz:
Java'da hangi veri türlerini kullanırsınız (Tarih, Takvim, uzun, ...)?
Java tarafında, Java 8'i kullanabilirsiniz LocalDateTime. Mirası da kullanabilirsiniz Date, ancak Java 8 Tarih / Saat türleri değiştirilemez olduklarından daha iyidir ve bunları kaydederken yerel saat dilimine kayma yapmazlar.
Hazırda Bekletme tarafından desteklenen Java 8 Tarih / Saat türleri hakkında daha fazla bilgi için bu makaleye göz atın .
Şimdi bu soruya da cevap verebiliriz:
Eşleme için hangi ek açıklamaları kullanırsınız (örn. @Temporal)?
Bir zaman damgası varlık özelliğini eşlemek için LocalDateTimeveya tuşunu kullanıyorsanız,java.sql.Timestamp@Temporal HIbernate bu özelliğin JDBC Zaman Damgası olarak kaydedileceğini zaten bildiği .
Yalnızca kullanıyorsanız ek açıklamayı şu java.util.Dateşekilde belirtmeniz gerekir @Temporal:
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "created_on")
private Date createdOn;
Ancak, bu şekilde eşleştirmeniz çok daha iyidir:
@Column(name = "created_on")
private LocalDateTime createdOn;
Denetim sütunu değerleri nasıl oluşturulur?
Üçüncü sorunuz:
Zaman damgalarını (veritabanı, ORM çerçevesi (Hazırda Bekletme) veya uygulama programcısı) ayarlamaktan kim sorumludur?
Eşleme için hangi ek açıklamaları kullanırsınız (örn. @Temporal)?
Bu hedefe ulaşmanın birçok yolu vardır. Veritabanının bunu yapmasına izin verebilirsiniz.
create_onSütun için aşağıdakiler DEFAULTgibi bir DDL kısıtlaması kullanabilirsiniz :
ALTER TABLE post
ADD CONSTRAINT created_on_default
DEFAULT CURRENT_TIMESTAMP() FOR created_on;
İçin updated_onsütunda, sizinle sütun değerini ayarlamak için bir DB tetiği kullanabilirsinizCURRENT_TIMESTAMP() belirli bir satır her değiştirildiğinde zaman.
Veya bunları ayarlamak için JPA veya Hazırda Beklet'i kullanın.
Aşağıdaki veritabanı tablolarına sahip olduğunuzu varsayalım:

Ve her tabloda aşağıdaki gibi sütunlar bulunur:
created_by
created_on
updated_by
updated_on
Hazırda Beklet @CreationTimestampve@UpdateTimestamp ek açıklamaları
Hazırda Beklet @CreationTimestampve @UpdateTimestampile eşleştirmek için kullanılabilecek ek açıklamaları created_onveupdated_on sütunlarını .
@MappedSuperclassTüm varlıklar tarafından genişletilecek bir temel sınıf tanımlamak için kullanabilirsiniz :
@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
}
Ve tüm varlıklar şu şekilde genişletilir 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
}
Kullanımı hakkında daha fazla bilgi için bu makaleye@MappedSuperclass göz atın .
Bununla birlikte, olsa bile createdOnve updateOnözellikleri hazırda-spesifik tarafından ayarlanır @CreationTimestampve @UpdateTimestampek açıklamalar createdByve updatedByaşağıdaki JPA çözeltisi ile gösterildiği gibi, bir uygulama geri arama kayıt gerektirmektedir.
JPA kullanma @EntityListeners
Denetim özelliklerini Yerleştirilebilir öğeye ekleyebilirsiniz:
@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
}
Ve AuditListenerdenetim özelliklerini ayarlamak için bir oluşturun :
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());
}
}
Kaydolmak için JPA ek açıklamasını AuditListenerkullanabilirsiniz @EntityListeners:
@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 ile denetim mülkleri uygulama hakkında daha fazla bilgi için bu makaleye@EntityListener göz atın .