History of database modifications with Hibernate
By Martin Cabrera
Envers is one of the Hibernate’s project sponsored by Redhat. Works with Hibernate and Hibernate Entity Manager.
Aims to enable easy auditing of persistent classes. For each audited entity you must annotate your persistent clases with @Audited, a table will be created, which will hold the history of changes made to the entity.
The idea is very similar to CVS or Subersion. Each transaction with updates, deletes or inserts made in the database with hibernate generate a new revision number. One transaction is one revision.
Envers provide a simple way to retrive your data of a revision using: revision number, date, queries with min and max function between others.
You can use Envers wherever Hibernate works: standalone, inside JBoss AS, with JBoss Seam or Spring.
It’s very easy …
1 2 3 4 5 6 7 8 9 10 11 |
@Entity @Audited public class User { private Long id; @Id @GeneratedValue public Long getId() { return id; } public void setId(Long id) { this.id = id; } // other fields and methods ... } |
Envers configuration
When configuring your Hibernate (persistence.xml
if you are using JPA, hibernate.cfg.xml
or other if you are using Hibernate directly), add the following event listeners:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<persistence-unit ...> <provider>org.hibernate.ejb.HibernatePersistence</provider> <class>...</class> <properties> <property name="hibernate.dialect" ... /> <!-- other hibernate properties --> <property name="hibernate.ejb.event.post-insert" value="org.hibernate.ejb.event.EJB3PostInsertEventListener,org.hibernate.envers.event.AuditEventListener" /> <property name="hibernate.ejb.event.post-update" value="org.hibernate.ejb.event.EJB3PostUpdateEventListener,org.hibernate.envers.event.AuditEventListener" /> <property name="hibernate.ejb.event.post-delete" value="org.hibernate.ejb.event.EJB3PostDeleteEventListener,org.hibernate.envers.event.AuditEventListener" /> <property name="hibernate.ejb.event.pre-collection-update" value="org.hibernate.envers.event.AuditEventListener" /> <property name="hibernate.ejb.event.pre-collection-remove" value="org.hibernate.envers.event.AuditEventListener" /> <property name="hibernate.ejb.event.post-collection-recreate" value="org.hibernate.envers.event.AuditEventListener" /> </properties> </persistence-unit> |
Then, annotate your persistent class with @Audited (like the User example)
And that’s it!
Queries
Find audited data
You can access the audit (history) of an entity using the AuditReader
interface, which you can obtain when having an open EntityManager.
1 2 |
AuditReader reader = AuditReaderFactory.get(entityManager); User oldUser = reader.find(User.class, userId, revision) |
Search a revision number
the whole documentation is in the Web site: https://docs.jboss.org/envers/docs/index.html#queries
To ilustrate one example I show the way to search the max number revision of one Entity audited.
1 2 3 4 |
Number revision = (Number) reader.createQuery().forRevisionsOfEntity(User.class, false, true) .addProjection(AuditEntity.revisionNumber().max()) .add(AuditEntity.id().eq(userId)) .getSingleResult(); |
We use Envers in a few projects. Works fine and very quickly, we recomended … no dubt ! Envers
Web site: www.jboss.org/envers
Envers documentation: https://docs.jboss.org/envers/docs/index.html