Java.Hibernate.Middle.How do you implement auditing/versioning for entities in Hibernate?

How do you implement auditing/versioning for entities in Hibernate?

🔎 Option 1: Hibernate Envers (recommended)

Envers is built into Hibernate → it provides automatic auditing of entity changes without requiring manual code to persist history.

How it works:

  • Envers creates an audit table for each audited entity, e.g., my_entity_AUD.
  • Every time an entity changes, Envers stores a new version in the audit table.
  • You can query historical states easily.

Steps to use Envers:

✅ 1) Add Envers dependency:

<dependency>
  <groupId>org.hibernate.orm</groupId>
  <artifactId>hibernate-envers</artifactId>
</dependency>

✅ 2) Annotate entities with @Audited:

@Entity
@Audited
public class Order {
    @Id
    private Long id;

    private String status;

    private double amount;
}
REVREVTYPEIDSTATUSAMOUNT
1042NEW100.0
2142PAID100.0

REVTYPE tells the change type: 0=INSERT, 1=UPDATE, 2=DELETE.

✅ 4) Query historical data:

AuditReader reader = AuditReaderFactory.get(entityManager);
Order oldOrder = reader.find(Order.class, 42L, 1); // revision 1

🔎 Option 2: Manual auditing (simpler but limited)

✅ Add fields to your entity:

@Entity
public class Order {
    @Id
    private Long id;

    private String status;

    private double amount;

    private String createdBy;
    private LocalDateTime createdAt;
    private String updatedBy;
    private LocalDateTime updatedAt;
}

✅ Use JPA callbacks or Spring’s @EntityListeners to set audit fields automatically:

@PrePersist
public void onCreate() {
    createdAt = LocalDateTime.now();
    createdBy = getCurrentUser();
}

@PreUpdate
public void onUpdate() {
    updatedAt = LocalDateTime.now();
    updatedBy = getCurrentUser();

✅ This approach only tracks the latest change, not full history.

🔎 Option 3: Interceptors or event listeners

For more control, Hibernate’s Interceptor or EventListener lets you capture every entity operation globally.

Example with Interceptor:

public class AuditInterceptor extends EmptyInterceptor {
    @Override
    public boolean onFlushDirty(
        Object entity, Serializable id, Object[] currentState,
        Object[] previousState, String[] propertyNames, Type[] types) {

        if (entity instanceof AuditableEntity) {
            // set updatedBy, updatedAt, etc.
        }
        return super.onFlushDirty(entity, id, currentState, previousState, propertyNames, types);
    }
}

📌 Key Takeaways

✅ Use Hibernate Envers for robust, out-of-the-box entity versioning → supports easy history querying.
✅ Use manual audit fields with listeners for simpler created/updated tracking.
✅ Advanced: interceptors or event listeners let you customize auditing globally.

This entry was posted in Без рубрики. Bookmark the permalink.