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, TIMESTAMP
sü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, DATETIME
bunun üst sınır sınırlaması olmayan daha iyi kullanım . Ancak, DATETIME
saat dilimi farkında değildir. Bu nedenle, veritabanı tarafında UTC kullanmak ve hibernate.jdbc.time_zone
Hibernate ö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 LocalDateTime
veya 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_on
Sütun için aşağıdakiler DEFAULT
gibi bir DDL kısıtlaması kullanabilirsiniz :
ALTER TABLE post
ADD CONSTRAINT created_on_default
DEFAULT CURRENT_TIMESTAMP() FOR created_on;
İçin updated_on
sü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 @CreationTimestamp
ve@UpdateTimestamp
ek açıklamaları
Hazırda Beklet @CreationTimestamp
ve @UpdateTimestamp
ile eşleştirmek için kullanılabilecek ek açıklamaları created_on
veupdated_on
sütunlarını .
@MappedSuperclass
Tü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 createdOn
ve updateOn
özellikleri hazırda-spesifik tarafından ayarlanır @CreationTimestamp
ve @UpdateTimestamp
ek açıklamalar createdBy
ve updatedBy
aş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 AuditListener
denetim ö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ı AuditListener
kullanabilirsiniz @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 .