Introduction
Auditing is one of the crucial part of software applications. It is required to manage the changes of aquired data and to keep applications safe from unethical access. Triggers are also implemented for this purpose but Hibernate gives a more easy and convenient way to implement auditing.
Hibernate Envers
Hibernate Envers is useful to create an audit log that documents all changes that were performed on the managed data. It saves this data on database itself. It only takes a few annotations to document all changes in the audit tables. It also provides a powerful API to extract information from your audit log.
Implementation
To add Hibernate Envers to an existing application, the first step is to add the following dependency:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-envers</artifactId>
<version>5.4.0.Final</version>
</dependency>
The next thing is to add @Audited annotation on top of that entity class whose audit log you want to create.
And that's it! You can create, modify and delete the entities as always. The generated schema does not affect adding auditing for the entities. Also, the data they hold is the same. There are, however, new table(s) - tablename_AUD, which store the historical data, whenever you commit a transaction.
Using this method, you can annotate only some persistent properties with @Audited, instead of annotating the whole class and auditing all properties.
To access the audit(history) of an entity, the AuditReader interface can be used which can be obtained when having an open EntityManager.
AuditReader reader = AuditReaderFactory.get(entityManager);
Person oldPerson = reader.find(Person.class, personId, revision)
The find() method returns an entity with the given primary key, with the data it contained at the given revision. If the entity didn't exist at this revision then the null value is returned.
To get a list of revisions at which an entity was modified, you can use the get revisions() method. And to retrieve the date at which a revision was created, you can use the getRevisionDate() method.
Thank You