Working with JPA Entity Lifecycle
1. Understanding Entity States
| State | Description |
|---|---|
| Transient | New new Entity() — no DB row, not in context |
| Managed | Tracked by persistence context; changes auto-flushed |
| Detached | Was managed; context closed or evicted |
| Removed | Marked for deletion; row deleted on flush |
Entity State Transitions
Transient ──persist()──> Managed ──remove()──> Removed
↓ ↑
detach()/close() merge()
↓ ↑
Detached
2. Using Lifecycle Callbacks (@PrePersist, @PostPersist)
Example: Auto-set timestamp and UUID on pre-persist
@Entity
public class User {
@PrePersist
void prePersist() {
if (createdAt == null) createdAt = Instant.now();
if (uuid == null) uuid = UUID.randomUUID();
}
@PostPersist void postPersist() { /* event */ }
}
3. Using @PreUpdate and @PostUpdate Callbacks
| Callback | Fired |
|---|---|
@PreUpdate |
Before UPDATE SQL |
@PostUpdate |
After UPDATE SQL |
| Use | Maintain updatedAt, audit fields |
4. Using @PreRemove and @PostRemove Callbacks
Example: Clean up file on entity removal
@Entity
public class Document {
@PreRemove
void cleanupFiles() { Files.deleteIfExists(Path.of(filePath)); }
}
5. Using @PostLoad Callback
| Callback | Use Case |
|---|---|
@PostLoad |
Decrypt fields, init computed transient fields |
6. Creating Entity Listeners (@EntityListeners)
Example: Entity listener for audit events
public class AuditListener {
@PrePersist void onCreate(Object e) { /* … */ }
@PreUpdate void onUpdate(Object e) { /* … */ }
}
@Entity
@EntityListeners({AuditListener.class, AuditingEntityListener.class})
public class Order { /* … */ }
7. Using Auditing (@CreatedDate, @LastModifiedDate)
Example: Audit base entity with Spring Data auditing
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseEntity {
@CreatedDate Instant createdAt;
@LastModifiedDate Instant updatedAt;
@CreatedBy String createdBy;
@LastModifiedBy String updatedBy;
@Version Long version;
}
8. Enabling JPA Auditing (@EnableJpaAuditing)
| Annotation | Element |
|---|---|
@EnableJpaAuditing |
On @Configuration / main class |
auditorAwareRef |
Bean providing current user |
dateTimeProviderRef |
Custom timestamp source |
9. Using @CreatedBy and @LastModifiedBy
Example: Current user from SecurityContext for auditing
@Bean
AuditorAware<String> auditorAware() {
return () -> Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication())
.map(Authentication::getName);
}
10. Implementing Custom Auditing Logic
| Approach | Detail |
|---|---|
| Hibernate Envers | Full revision history tables (_AUD) |
| App-managed audit table | Insert audit rows in service or listener |
| Domain events | Publish AggregateLifecycleEvent via AbstractAggregateRoot |