Entity listeners in JPA are used to react to lifecycle events of entities, such as creation, update, or deletion. They allow you to execute logic automatically whenever certain events occur, without polluting your service or repository layer with repetitive code.
Here’s a detailed explanation with a scenario:
1. What Are Entity Listeners
- JPA defines several entity lifecycle callbacks:
@PrePersist
→ Before an entity is inserted@PostPersist
→ After an entity is inserted@PreUpdate
→ Before an entity update@PostUpdate
→ After an entity update@PreRemove
→ Before an entity deletion@PostRemove
→ After an entity deletion@PostLoad
→ After an entity is loaded from the database
- Entity listeners are classes or methods annotated to listen to these events.
2. Scenario: Audit Logging
Imagine an e-commerce application with an Order
entity. You want to track when an order is created or updated, and maybe also log it or update audit fields (createdAt
, updatedAt
).
Instead of manually setting timestamps in every service method, you can use an entity listener.
Step 1: Create Listener Class
import jakarta.persistence.PrePersist; import jakarta.persistence.PreUpdate; import java.time.LocalDateTime; public class AuditListener { @PrePersist public void prePersist(Object entity) { if (entity instanceof Auditable) { Auditable auditable = (Auditable) entity; auditable.setCreatedAt(LocalDateTime.now()); auditable.setUpdatedAt(LocalDateTime.now()); } } @PreUpdate public void preUpdate(Object entity) { if (entity instanceof Auditable) { Auditable auditable = (Auditable) entity; auditable.setUpdatedAt(LocalDateTime.now()); } } }
- The listener handles all entities that extend
Auditable
. - Automatically sets
createdAt
andupdatedAt
without repeating logic in every service method.
Step 2: Attach Listener to Entity or Base Class
Option 1: Per Entity
import jakarta.persistence.*; @Entity @EntityListeners(AuditListener.class) public class Order extends Auditable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String status; }
Option 2: Base Class
@MappedSuperclass @EntityListeners(AuditListener.class) public abstract class Auditable { private LocalDateTime createdAt; private LocalDateTime updatedAt; // Getters and setters }
- Now all entities inheriting from
Auditable
automatically get audit timestamps.
3. Other Common Use Cases for Entity Listeners
- Audit Logging
- Automatically set
createdBy
orupdatedBy
.
- Automatically set
- Soft Deletes
- Instead of physically deleting, set a
deletedAt
timestamp in@PreRemove
.
- Instead of physically deleting, set a
- Validation
- Enforce certain business rules before insert/update.
- Integrating with External Systems
- Trigger notifications or events after certain entity changes using
@PostPersist
or@PostUpdate
.
- Trigger notifications or events after certain entity changes using
- Automatic Encryption or Transformation
- Encrypt sensitive fields before saving to the database.
4. Benefits of Entity Listeners
- Centralized logic → avoids repeating code in service layer.
- Decouples concerns → entity behavior is separate from business logic.
- Automatic handling → runs on every entity lifecycle event.
- Works well with base classes for reusable logic (like auditing).
5. Example in Action
Order order = new Order(); order.setStatus("CREATED"); orderRepository.save(order); // AuditListener sets createdAt and updatedAt automatically
- Updating the order later:
order.setStatus("SHIPPED"); orderRepository.save(order); // updatedAt updated automatically