5.1 Məlumatların dəyişmə vaxtı
Məlumatlar bazasında müxtəlif qeydləri uzun illər saxladıqda, çox vaxt iki sual yaranır:
- Bu qeyd nə vaxt məlumatlar bazasına əlavə olunub?
- Bu qeyd sonuncu dəfə nə zaman dəyişib?
Bu qədər tez-tez rast gəlinən məsələlərdir ki, demək olar ki, hər bir cədvələ məlumatlar bazasında iki kolon əlavə edirlər:
- created_time
- updated_time
Birincidə qeydin yaradılma tarixi və vaxtı saxlanılır, ikincidə isə – onun sonuncu dəyişmə tarixi və vaxtı. Və hər bir Entity sinfində sahələr var:
@Entity
@Table(name = "entities")
public class Entity {
...
@Column(name="created_time")
private Date created;
@Column(name="updated_time")
private Date updated;
}
Hibernate obyektlərin məlumatlar bazasındakı yenilənmə zamanı idarə edilməsini iki annotasiya ilə öz üzərinə götürə bilər: @CreationTimestamp
və @UpdateTimestamp
.
Nümunə:
@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;
}
Bu annotasiyalarla işarələnmiş kolonlarda obyektin yaradılma və sonuncu dəyişilmə vaxtı həmişə düzgün saxlanacaq.
5.2 Annotasiya @PrePersist
Əgər obyektin vaxtını idarə etmək üçün daha mürəkkəb ssenarilər lazım olsa, Hibernate-də bunun üçün annotasiyalar var. Sinifin metodlarını bu annotasiyalarla işarələyə bilərsən və Hibernate obyekti məlumatlar bazasına saxlayarkən bu metodları çağıracaq. Cəmi 7 belə annotasiya var:
@PrePersist | Obyekti məlumatlar bazasına saxlayarkən çağırılır. (SQL INSERT) |
@PostPersist | Obyekti məlumatlar bazasına saxladıqdan dərhal sonra çağırılır. (SQL INSERT) |
@PreRemove | Obyekti məlumatlar bazasından silməzdən əvvəl çağırılır. |
@PostRemove | Obyekti məlumatlar bazasından sildikdən sonra çağırılır. |
@PreUpdate | Obyekti məlumatlar bazasında yeniləmədən əvvəl çağırılır. (SQL UPDATE) |
@PostUpdate | Obyekti məlumatlar bazasında yenilədikdən sonra çağırılır. (SQL UPDATE) |
@PostLoad | Obyekti məlumatlar bazasından yüklədikdən sonra çağırılır. |
Gəl, bir nümunə yazaq, burada sinifin obyektlərinin yaradılma və yenilənmə vaxtını doğru qeyd edirik:
@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 obyekti ilk dəfə saxlayanda, @PrePersist
annotasiyası ilə işarələnmiş metodu çağıracaq. Məlumatlar bazasında mövcud olan obyekti yeniləyərkən, @PreUpdate
annotasiyası ilə işarələnmiş metodu çağıracaq.
5.3 Öz EntityListeners əlavə edirik
Əgər çox ehtiyac varsa, Hibernate-in çağırdığı metodları, onları çağırdığı obyektdən ayıra bilirsən. JPA spesifikasiyası sənə listener-sinifləri elan etməyə imkan verir, bunlar Entity-obyektlərinin müəyyən işləmə anlarında çağırılacaq.
Əgər çox oxşar Entity-obyektlərin varsa, onların bir hissəsini əsas sinifdə toplamaq və onların davranışını idarə edəcək Listener əlavə etmək olar. Nümunə:
@MappedSuperclass
public abstract class BaseEntity {
private Timestamp createdOn;
private Timestamp updatedOn;
}
@Entity
public class User extends BaseEntity {
@Id
private Long id;
private String name;
}
Onda BaseEntity sinfi üçün xüsusi listener-sinif yarada bilərik:
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) );
}
}
Və User sinfi ilə onun listener-in əlaqələndirmək üçün bir neçə annotasiya istifadə edə bilərik:
@Entity @EntityListeners(class= TimeEntityListener.class)
public class User extends BaseEntity {
@Id
private Long id;
private String name;
}
GO TO FULL VERSION