5.1 Tijdstip van gegevenswijziging
Wanneer u verschillende records jarenlang in een database opslaat, ontstaan er vaak twee vragen:
- Wanneer is dit item aan de database toegevoegd?
- Wanneer is deze invoer voor het laatst gewijzigd?
Dit zijn zulke frequente taken dat er aan bijna elke tabel in de database twee kolommen worden toegevoegd:
- gemaakt_tijd
- bijgewerkt_tijd
De eerste slaat de datum en tijd op waarop de record is gemaakt en de tweede slaat de datum en tijd op waarop deze voor het laatst is gewijzigd. En elke Entity-klasse heeft velden:
@Entity
@Table(name = "entities")
public class Entity {
...
@Column(name="created_time")
private Date created;
@Column(name="updated_time")
private Date updated;
}
Hibernate kan al het werk doen om te controleren wanneer objecten in de database worden bijgewerkt met twee annotaties @CreationTimestamp
en @UpdateTimestamp
.
Voorbeeld:
@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;
}
De kolommen gemarkeerd met deze annotaties zullen altijd de juiste tijd opslaan waarop het object is gemaakt en wanneer het voor het laatst is gewijzigd.
5.2 @PrePersist-annotatie
Als je meer complexe scripts nodig hebt om de tijd van een object te regelen, dan heeft Hibernate ook annotaties voor dit geval. Ze kunnen klassemethoden markeren en Hibernate zal deze methoden aanroepen wanneer het object in de database wordt opgeslagen. Er zijn in totaal 7 van dergelijke annotaties:
@PrePersist | Aangeroepen voordat het object wordt opgeslagen in de database. (SQL-INSERT) |
@PostPersist | Onmiddellijk aangeroepen nadat het object in de database is opgeslagen. (SQL-INSERT) |
@PreRemove | Wordt aangeroepen voordat een object in de database wordt verwijderd. |
@PostVerwijderen | Aangeroepen nadat een object uit de database is verwijderd. |
@PreUpdate | Aangeroepen voordat een object in de database wordt bijgewerkt (SQL UPDATE). |
@PostUpdate | Aangeroepen na een update (SQL UPDATE) van een object in de database. |
@PostLoad | Aangeroepen nadat het object uit de database is geladen. |
Laten we een voorbeeld schrijven waarin we een klas vertellen wat de juiste tijd is om zijn objecten te maken en bij te werken:
@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();
}
}
Als Hibernate het object voor de eerste keer opslaat, roept het de methode aan die is geannoteerd met @PrePersist
. Als het een bestaand object in de database bijwerkt, roept het de methode gemarkeerd met de annotatie aan @PreUpdate
.
5.3 Onze EntityListeners toevoegen
Als het echt nodig is, kunt u de methoden die Hibernate aanroept, scheiden van het object waarop het ze aanroept. Met de JPA-specificatie kunt u listenerklassen declareren die op bepaalde tijden worden aangeroepen bij het verwerken van Entity-objecten.
Als u veel vergelijkbare Entity-objecten hebt, kunt u een aantal ervan naar de basisklasse verplaatsen en een Listener toevoegen die hun gedrag regelt. Voorbeeld:
@MappedSuperclass
public abstract class BaseEntity {
private Timestamp createdOn;
private Timestamp updatedOn;
}
@Entity
public class User extends BaseEntity {
@Id
private Long id;
private String name;
}
Vervolgens kunt u voor de BaseEntity-klasse een speciale luisteraarsklasse maken:
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) );
}
}
En u kunt de User-klasse en zijn luisteraar verbinden met behulp van een aantal annotaties:
@Entity
@EntityListeners(class= TimeEntityListener.class)
public class User extends BaseEntity {
@Id
private Long id;
private String name;
}