Home/Learn/Hibernate & JPA/Hibernate Envers (Entity Auditing)

Hibernate Envers (Entity Auditing)

Advanced
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.

Java — @Audited entity and generated audit tables
<!-- 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.

Java — AuditReader for entity history queries
@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.

Java — RevisionRepository for audit history
// 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 Aria
1

What tables does Hibernate Envers create for an @Audited entity?

EasyTCS
2

How do you retrieve the state of an entity at a specific point in time using Envers?

MediumAmazon
3

What are the three RevisionType values and what do they represent?

MediumInfosys
4

How does @NotAudited affect the audit trail?

EasyWipro
5

What is the write overhead of using Hibernate Envers in production?

HardOracle

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.

Loading discussion…