Issue
Hibernate Envers Is there an implementation of org.hibernate.envers.Audited in the JPA? What is the best way to apply data versioning when using Spring Data JPA technology? What dependencies need to be included? Please share your experience. How about Spring Data extension to work with Hibernate Envers?
Solution
Hibernate envers
- Once the Envers-project jar file has been added to the classpath (or depending on Maven), it can be used without further configuration.
- An entity class can be selectively audited using the @org.hibernate.envers.Audited annotation on an entity. By marking a class with this annotation, hibernate will version all properties, including collections. To exclude a property, you need to mark the class field (collection, relation) with the @org.hibernate.envers.NotAudited annotation.
- Hibernate will generate (or look up) additional tables in the database to store archived data for each entity instance annotated with the @org.hibernate.envers.Audited annotation.
The change history is stored in the SOME_ENTITY_AUD tables corresponding to the SomeEntity instances. A REVINFO table is also created. When the data changes and then commits the transaction, Hibernate will store the new version number with a timestamp in the REVINFO table. The SOME_ENTITY_AUD table additionally has two fields 1) REV << PK >> << FK >> - a reference to REVINFO, 2) The REVTYPE column stores the change type: whether a particular entity instance was added, changed or removed during the transaction.
Envers never deletes version information and archived data; even after calling the remove() method on a SomeEntity instance, its previous version will still be stored in the SOME_ENTITY_AUD table.
GET AUDIT DATA:
Using the Envers AuditReader interface, you can find the version number for each set of changes:
AuditReader auditReader = AuditReaderFactory.get(em);
Search for sets:
List<Number> itemRevisions = auditReader.getRevisions(Item.class, ITEM_ID);
Getting timestamp:
for (Number itemRevision : itemRevisions) {
Date itemRevisionTimestamp = auditReader.getRevisionDate(itemRevision);
// ...
}
Get the version number:
Number revisionUpdate = auditReader.getRevisionNumberForDate(TIMESTAMP);
Entity lookup:
SomeEntity someEntity = auditReader.find(Item.class, ITEM_ID, revisionUpdate);
If neither timestamps nor version numbers are known, you can create a query using the forRevisionsOfEntity() method and retrieve all entries from the audit log for a particular entity.
Answered By - Andrew Dark
Answer Checked By - Katrina (JavaFixing Volunteer)