Lifecycle callbacks and auditing
Stamp created and updated columns automatically, and know exactly when each hook runs.
Open this lesson in the learning hubKey points
- JPA gives you
@PrePersist,@PreUpdateand@PreRemove, their @Post twins, and @PostLoad after a read. @PreUpdateonly fires when dirty checking found a real change. No change means no UPDATE and no callback.- Callbacks run inside the flush. Never call a repository, publish an event or touch another entity from one.
- Spring Data auditing is tidier:
@CreatedDate,@LastModifiedDateand@CreatedByon a base class. - It needs
@EnableJpaAuditing,@EntityListenerson the class, and anAuditorAwarebean for the user. - Two timestamps are not history. For who changed what, and when, add Hibernate Envers and get a real revision table.
Example
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class Auditable {
@CreatedDate @Column(updatable = false) private Instant createdAt;
@LastModifiedDate private Instant updatedAt;
@CreatedBy @Column(updatable = false) private String createdBy;
}
@Entity
public class Book extends Auditable {
@Id @GeneratedValue private Long id;
private String title;
private String slug;
@PrePersist
@PreUpdate
void normalise() { // pure, local, no other entity touched
this.slug = title.toLowerCase().replace(" ", "-");
}
}
@Configuration
@EnableJpaAuditing
class AuditConfig {
@Bean
AuditorAware<String> auditorAware() {
return () -> Optional.ofNullable(SecurityContextHolder.getContext())
.map(c -> c.getAuthentication().getName());
}
}
Let the framework stamp the audit columns; keep your own callbacks local.
This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Hibernate course, and every lesson in it is listed on the Hibernate contents page.