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