1. आपको किस डेटाबेस कॉलम का उपयोग करना चाहिए
आपका पहला सवाल था:
डेटाबेस में आप किस प्रकार के डेटा का उपयोग करेंगे (MySQL मानते हुए, संभवत: एक अलग टाइमज़ोन कि JVM में)? क्या डेटा के प्रकार टाइमजोन-जागरूक होंगे?
MySQL में, TIMESTAMP
कॉलम प्रकार JDBC ड्राइवर स्थानीय समय क्षेत्र से डेटाबेस टाइमज़ोन पर शिफ्टिंग करता है, लेकिन यह केवल टाइमस्टैम्प को स्टोर कर सकता है '2038-01-19 03:14:07.999999
, इसलिए यह भविष्य के लिए सबसे अच्छा विकल्प नहीं है।
इसलिए, DATETIME
इसके बजाय बेहतर उपयोग , जिसमें यह ऊपरी सीमा सीमा नहीं है। हालांकि, DATETIME
टाइमजोन जागरूक नहीं है। तो, इस कारण से, डेटाबेस की ओर से यूटीसी का उपयोग करना और hibernate.jdbc.time_zone
हाइबरनेट संपत्ति का उपयोग करना सबसे अच्छा है ।
hibernate.jdbc.time_zone
सेटिंग के बारे में अधिक जानकारी के लिए , इस लेख को देखें ।
2. आपको किस इकाई की संपत्ति का उपयोग करना चाहिए
आपका दूसरा प्रश्न था:
आप जावा (दिनांक, कैलेंडर, दीर्घ, ...) में किस प्रकार के डेटा का उपयोग करेंगे?
जावा पक्ष पर, आप जावा 8 का उपयोग कर सकते हैं LocalDateTime
। आप विरासत का उपयोग भी कर सकते हैं Date
, लेकिन जावा 8 दिनांक / समय प्रकार बेहतर हैं क्योंकि वे अपरिवर्तनीय हैं, और उन्हें लॉग करते समय स्थानीय समय क्षेत्र में शिफ्ट करने के लिए टाइमज़ोन नहीं करते हैं।
हाइबरनेट द्वारा समर्थित जावा 8 दिनांक / समय प्रकार के बारे में अधिक जानकारी के लिए, इस लेख को देखें ।
अब, हम इस प्रश्न का उत्तर भी दे सकते हैं:
मैपिंग के लिए आप किस एनोटेशन का उपयोग करेंगे (जैसे @Temporal
)?
यदि आप टाइमस्टैम्प इकाई संपत्ति का उपयोग कर रहे हैं LocalDateTime
या java.sql.Timestamp
मैप करने के लिए उपयोग कर रहे हैं, तो आपको उपयोग करने की आवश्यकता नहीं है @Temporal
क्योंकि HIbernate को पहले से ही पता है कि इस संपत्ति को JDBC टाइमस्टैम्प के रूप में सहेजा जाना है।
केवल यदि आप उपयोग कर रहे हैं java.util.Date
, तो आपको @Temporal
एनोटेशन निर्दिष्ट करने की आवश्यकता है , जैसे:
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "created_on")
private Date createdOn;
लेकिन, अगर आप इसे इस तरह से मैप करते हैं तो यह बहुत बेहतर है:
@Column(name = "created_on")
private LocalDateTime createdOn;
ऑडिट कॉलम मान कैसे उत्पन्न करें
आपका तीसरा प्रश्न था:
आप टाइमस्टैम्प-डेटाबेस, ओआरएम फ्रेमवर्क (हाइबरनेट), या एप्लिकेशन प्रोग्रामर को स्थापित करने के लिए किसे जिम्मेदार ठहराएंगे?
मैपिंग के लिए आप किस एनोटेशन का उपयोग करेंगे (उदाहरण @Temporal)?
इस लक्ष्य को प्राप्त करने के कई तरीके हैं। आप डेटाबेस को ऐसा करने की अनुमति दे सकते हैं।
के लिए create_on
स्तंभ, आप एक इस्तेमाल कर सकते हैं DEFAULT
जैसे DDL बाधा,:
ALTER TABLE post
ADD CONSTRAINT created_on_default
DEFAULT CURRENT_TIMESTAMP() FOR created_on;
के लिए updated_on
स्तंभ, आप एक डीबी ट्रिगर का उपयोग स्तंभ मान के साथ स्थापित करने के लिए कर सकता है CURRENT_TIMESTAMP()
हर बार किसी पंक्ति संशोधित किया गया है।
या, उन्हें सेट करने के लिए JPA या हाइबरनेट का उपयोग करें।
मान लें कि आपके पास निम्नलिखित डेटाबेस टेबल हैं:
और, प्रत्येक तालिका में कॉलम हैं:
created_by
created_on
updated_by
updated_on
हाइबरनेट @CreationTimestamp
और @UpdateTimestamp
एनोटेशन का उपयोग करना
सीतनिद्रा में होना @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
निम्नलिखित जेपीए समाधान द्वारा सचित्र के रूप में, एप्लिकेशन कॉलबैक को पंजीकृत करने की आवश्यकता होती है।
जेपीए का उपयोग करना @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
}
जेपीए के साथ ऑडिट गुणों को लागू करने के बारे में अधिक जानकारी के लिए @EntityListener
, इस लेख को देखें ।