Hibernate.orgCommunity Documentation

Chapter 1. Quickstart

If you're using JPA, when coniguring Hibernate (in persistence.xml), add the following event listeners: (this will allow Envers to check if any audited entities were modified)

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

If you're using Hibernate directly, add the following to hibernate.cfg.xml:

	<hibernate-configuration>
	<session-factory>

	<listener class="org.hibernate.envers.event.AuditEventListener" type="post-insert"/>
	<listener class="org.hibernate.envers.event.AuditEventListener" type="post-update"/>
	<listener class="org.hibernate.envers.event.AuditEventListener" type="post-delete"/>
	<listener class="org.hibernate.envers.event.AuditEventListener" type="pre-collection-update"/>
	<listener class="org.hibernate.envers.event.AuditEventListener" type="pre-collection-remove"/>
	<listener class="org.hibernate.envers.event.AuditEventListener" type="post-collection-recreate"/>


	</session-factory>
	</hibernate-configuration>
    

The EJB3Post...EvenListeners are needed, so that ejb3 entity lifecycle callback methods work (@PostPersist, @PostUpdate, @PostRemove.

Then, annotate your persistent class with @Audited - this will make all properties audited. For example:

import org.hibernate.envers.Audited;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue;
import javax.persistence.Column;

@Entity
@Audited // that's the important part :)
public class Person {
    @Id
    @GeneratedValue
    private int id;

    private String name;

    private String surname;

    @ManyToOne
    private Address address;

    // add getters, setters, constructors, equals and hashCode here
}

And the referenced entity:

@Entity
@Audited
public class Address {
    @Id
    @GeneratedValue
    private int id;

    private String streetName;

    private Integer houseNumber;

    private Integer flatNumber;

    @OneToMany(mappedBy = "address")
    private Set<Person> persons;

    // add getters, setters, constructors, equals and hashCode here
}

And that's it! You create, modify and delete the entites as always. If you look at the generated schema, you will notice that it is unchanged by adding auditing for the Address and Person entities. Also, the data they hold is the same. There are, however, two new tables - Address_AUD and Person_AUD, which store the historical data, whenever you commit a transaction.

Instead of annotating the whole class and auditing all properties, you can annotate only some persistent properties with @Audited. This will cause only these properties to be audited.

You can access the audit (history) of an entity using the AuditReader interface, which you can obtain when having an open EntityManager.

AuditReader reader = AuditReaderFactory.get(entityManager);
Person oldPerson = reader.find(Person.class, personId, revision)

The T find(Class<T> cls, Object primaryKey, Number revision) 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, null is returned. Only the audited properties will be set on the returned entity. The rest will be null.

You can also get a list of revisions at which an entity was modified using the getRevisions method, as well as retrieve the date, at which a revision was created using the getRevisionDate method.