hibernate

Hibernate Envers Example

In many business applications, it is of utmost important to track the audit log, when and who has done the changes to the data. There are multiple approaches to achieve it. Hibernate Envers is one of the ways to achieve it. In this article, we will study the Hibernate Envers.

Envers are part of the Hibernate Core module. They aim to provide an easy way to auditing/ versioning the entity class. Envers provide an easy way to create and retrieve the audit logs.

1. Introduction

Envers can support both Hibernate and JPA. In fact, they can be used anywhere the hibernate works like Spring, WildFly, Grails ..etc. Some of the features offered by Envers are as follows,

  • Auditing of mapping definitions
  • Logging entity revisions
  • Querying of historical data
  • Support both JPA and Hibernate
  • Logging of custom mapping that extends JPA

2. Setup Hibernate Envers

Envers can easily set up and they have annotation support to keep developers’ work minimal. Below are the necessary steps to make Envers work,

  • Add hibernate-envers dependency in your project
  • Annotate the target entity classes with @Audited
  • Each of the entity should have an immutable primary key

3. Example

In this section, we will see how to enable auditing for our entity class.

Add hibernate-envers dependency to the pom.xml

Hibernate Envers
hibernate-envers

In the entity, class add @Audited annotation

Hibernate Envers - Audited annotation
Audited annotation

This annotation instructs hibernate to audit changes to this entity (Create, Update or Delete). From this point, hibernate will create new revision entry for each of the transaction on the annotated entity.

In the example program, I am going to

  • Create 2 employees
  • List employees
  • Update already created employees
  • Display audit logs

As shown earlier, auditing is enabled for the entity class. Hibernate creates auditing tables employee_aud and revinfo tables for us. When the main program is run below output (covers create, list and update employee record) can be seen in the console as I have enabled the hibernate logging,

Hibernate Envers - enver-example-output
enver-example-output

At the end of the program created entities are updated. The contents of the employee table are the following,

Hibernate Envers - employee table contents
employee table contents

Hibernate envers automatically creates logging entries in employee_aud and revinfo tables. Contents are as follows,

Audit Table: An audit table is created for each of the entities marked with @Audited annotation. Each audit table contains a primary key from the original entity, all the audited columns, revision type, and revision number.

employee_aud contents

Revinfo Table: This table maintains the revisions of the entity. It has an integer column revision number and timestamp as a bigint. By default hibernate persists only these two columns. However, it is possible to capture/save additional information as well.

revinfo table contents

3.1 Retrieving the audit record

In this section, I am going to show how can we retrieve the audit records created by the Hibernate Envers framework.

2 most probable use cases to view audit records are as follows,

  • Get all the revisions of an entity
  • Get the active revision of an entity at a given point in time

In the example program, I am going to show how to fetch all the revisions of an Employee entity.

HibernateRetrieveAuditRecordsDemo

public class HibernateRetrieveAuditRecordsDemo {
    public static void main(String[] args) {
        SessionFactory sessionfactory = HibernateUtil.getSessionFactory();
        Session session = sessionfactory.openSession();

        HibernateCreateAuditRecordsDemo.createEmployees(sessionfactory);
        HibernateCreateAuditRecordsDemo.updateEmployees(sessionfactory);
        System.out.println("################## Retrieving audit records ####################");
        
        AuditReader reader = AuditReaderFactory.get(session);
        AuditQuery q = reader.createQuery().forRevisionsOfEntity(Employee.class, false, true);

        q.add(AuditEntity.property("firstName").like("Santosh", MatchMode.ANYWHERE));
        List revisions = q.getResultList();

        System.out.println("Number of revisions fetched === " + revisions.size());
        revisions.forEach(objects -> {
            Employee empRecord = (Employee)objects[0];
            DefaultRevisionEntity revEntity = (DefaultRevisionEntity)objects[1];
            RevisionType revType = (RevisionType)objects[2];

            System.out.println(String.format("Employee ID:%d at revision %d with first name %s",
                    empRecord.getId(), revEntity.getId(), empRecord.getFirstName()));
        });
    }
}

The output of the above program is as below,

Revision details

The AuditQuery interface has many more capabilities to play with hibernate envers audit entities. As an exercise, you can add additional criteria to fetch the history at a given point in time.

4. Download the Source Code

In this section, I am providing a link to the example code.

What do you need to run the program?

  • Project is done using Java 11 and IntelliJ Idea IDE
  • Import the project using maven
  • Program uses PostgresSQL database
  • The program HibernateCreateAuditRecordsDemo demonstrates how audit entities are created
  • The program HibernateRetrieveAuditRecordsDemo demonstrates how audit entities can be retrieved
Download
You can download the full source code of this example here: Hibernate Enver Example

Santosh Balgar

He is a Software Engineer working in an industry-leading organization. He has completed his bachelors from Visweswaraya Technological University. In his career, he has worked in designing and implementing various software systems involving Java/J2EE, Spring/ Spring Boot, React JS, JQuery, Hibernate and related database technologies. He loves to share his knowledge and always look forward to learning and explore new technologies. He loves to spend his free time with his family. He enjoys traveling and loves to play cricket.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Naveen
Naveen
3 years ago

can we use Hibernate envers for redis(using as persistance storage) ??

Back to top button