Hibernate Envers (Entity Auditing)
Advanced@Audited on an entity instructs Envers to record every change in a revision table; query historical data with AuditReader to retrieve entity state at a specific revision.
Overview
Hibernate Envers provides entity versioning and auditing out of the box. Add @Audited to an entity and Envers automatically creates a mirror table (entity_aud) and a revision info table (revinfo). Every INSERT, UPDATE, and DELETE creates a new revision entry recording the entity state. You can query the full history of any entity, retrieve its state at a specific revision, find all revisions where a field changed, or list entities modified in a given revision. Spring Data Envers (spring-data-envers) provides a RevisionRepository interface for repository-style audit queries.
Enabling Envers
Add spring-boot-starter-data-jpa (includes Envers) and annotate the entity. Envers creates the audit table and REVINFO table automatically.
<!-- pom.xml — Envers is included in spring-boot-starter-data-jpa -->
<!-- For RevisionRepository, add spring-data-envers separately -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-envers</artifactId>
</dependency>
@Entity
@Audited // audit all fields
public class Product {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private BigDecimal price;
@NotAudited // exclude this field from auditing
private byte[] imageData;
}
// Envers generates:
// products_aud (id, rev, revtype, name, price)
// revinfo (rev SERIAL PK, revtstmp BIGINT)Querying Audit History with AuditReader
AuditReader provides low-level access to revision history. Find entity state at a specific revision or retrieve all revisions for an entity.
@Service
public class ProductAuditService {
@PersistenceContext EntityManager em;
public List<Object[]> getHistory(Long productId) {
AuditReader reader = AuditReaderFactory.get(em);
// Get list of revision numbers for this entity
List<Number> revisions = reader.getRevisions(Product.class, productId);
List<Object[]> history = new ArrayList<>();
for (Number rev : revisions) {
Product snapshot = reader.find(Product.class, productId, rev);
RevisionType type = reader.findRevision(DefaultRevisionEntity.class, rev).toString();
history.add(new Object[]{ rev, snapshot, type });
}
return history;
}
public Product getStateAtRevision(Long productId, int revision) {
AuditReader reader = AuditReaderFactory.get(em);
return reader.find(Product.class, productId, revision);
}
}Spring Data Envers — RevisionRepository
Spring Data Envers adds a RevisionRepository interface that provides findRevisions() and findLastChangeRevision() at the repository level without using AuditReader directly.
// Enable Spring Data Envers
@SpringBootApplication
@EnableJpaRepositories(repositoryFactoryBeanClass = EnversRevisionRepositoryFactoryBean.class)
public class Application { ... }
// Repository — extends RevisionRepository
public interface ProductRepository
extends JpaRepository<Product, Long>,
RevisionRepository<Product, Long, Integer> {
}
// Service usage
@Autowired ProductRepository repo;
Revisions<Integer, Product> revisions = repo.findRevisions(productId);
revisions.forEach(r ->
log.info("Rev {}: {} at {}", r.getRevisionNumber(), r.getEntity().getName(), r.getRevisionInstant()));
Optional<Revision<Integer, Product>> latest = repo.findLastChangeRevision(productId);Key Points to Remember
- 1@Audited creates a mirror _aud table and REVINFO table automatically
- 2@NotAudited on a field excludes it from the audit trail (e.g. large binary fields)
- 3AuditReader.find(Class, id, revision) retrieves entity state at a specific point in time
- 4RevisionType: ADD (insert), MOD (update), DEL (delete) — stored in each _aud row
- 5Spring Data Envers RevisionRepository provides findRevisions() and findLastChangeRevision()
- 6Envers adds write overhead — every persisted change requires an additional INSERT into the _aud table
Interview Questions
Sign in to ask AriaWhat tables does Hibernate Envers create for an @Audited entity?
How do you retrieve the state of an entity at a specific point in time using Envers?
What are the three RevisionType values and what do they represent?
How does @NotAudited affect the audit trail?
What is the write overhead of using Hibernate Envers in production?
Ask Aria about Hibernate Envers (Entity Auditing)
Your personal AI tutor — ask anything about this concept
Revision Status
Personal Notes
Sign in to save personal notes for this topic.
Discussion
Sign in to join the discussion.