5.1 Tidspunkt for endring av data
Når du lagrer ulike poster i en database i mange år, oppstår ofte to spørsmål:
- Når ble denne oppføringen lagt til databasen?
- Når ble denne oppføringen sist endret?
Dette er så hyppige oppgaver at to kolonner legges til i nesten hver tabell i databasen:
- opprettet_tid
- oppdatert_tid
Den første lagrer datoen og klokkeslettet da posten ble opprettet, og den andre lagrer datoen og klokkeslettet den sist ble endret. Og hver Entity-klasse har felt:
@Entity
@Table(name = "entities")
public class Entity {
...
@Column(name="created_time")
private Date created;
@Column(name="updated_time")
private Date updated;
}
Hibernate kan gjøre alt arbeidet med å kontrollere når objekter i databasen oppdateres med to merknader @CreationTimestamp
og @UpdateTimestamp
.
Eksempel:
@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;
}
Kolonnene merket med disse merknadene vil alltid lagre riktig tidspunkt da objektet ble opprettet og når det sist ble endret.
5.2 @PrePersist-kommentar
Hvis du trenger noen mer komplekse skript for å kontrollere tidspunktet for et objekt, så har Hibernate merknader for denne saken også. De kan merke klassemetoder, og Hibernate kaller disse metodene når den lagrer objektet i databasen. Det er 7 slike merknader totalt:
@PrePersist | Kalles før objektet er lagret i databasen. (SQL INSERT) |
@PostPersist | Kalt opp umiddelbart etter at objektet er lagret i databasen. (SQL INSERT) |
@Forhåndsfjern | Kalt før sletting av et objekt i databasen. |
@PostRemove | Kalt opp etter at et objekt er slettet fra databasen. |
@Forhåndsoppdatering | Kalt før oppdatering (SQL UPDATE) et objekt i databasen. |
@PostUpdate | Kalt etter en oppdatering (SQL UPDATE) av et objekt i databasen. |
@PostLoad | Kalt opp etter at objektet er lastet inn fra databasen. |
La oss skrive et eksempel der vi forteller en klasse riktig tidspunkt for å opprette og oppdatere objektene:
@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();
}
}
Hvis Hibernate lagrer objektet for første gang, vil det kalle opp metoden som er kommentert med @PrePersist
. Hvis den oppdaterer et eksisterende objekt i databasen, vil den kalle opp metoden merket med merknaden @PreUpdate
.
5.3 Legge til våre EntityListeners
Hvis du virkelig trenger det, kan du skille metodene som Hibernate kaller fra objektet den kaller dem på. JPA-spesifikasjonen lar deg deklarere lytterklasser som vil bli kalt til bestemte tider ved behandling av enhetsobjekter.
Hvis du har mange lignende Entity-objekter, kan du flytte noen av dem inn i basisklassen og legge til en Listener som kontrollerer oppførselen deres. Eksempel:
@MappedSuperclass
public abstract class BaseEntity {
private Timestamp createdOn;
private Timestamp updatedOn;
}
@Entity
public class User extends BaseEntity {
@Id
private Long id;
private String name;
}
Så for BaseEntity-klassen kan du opprette en spesiell lytterklasse:
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) );
}
}
Og du kan koble brukerklassen og dens lytter ved å bruke et par merknader:
@Entity
@EntityListeners(class= TimeEntityListener.class)
public class User extends BaseEntity {
@Id
private Long id;
private String name;
}