12.7.6. Queries
12.7.6.1. Retrieve Auditing Information
Hibernate Envers provides the functionality to retrieve audit information through queries. This topic provides examples of those queries.
Note
live
data, as they involve correlated subselects.
Example 12.33. Querying for Entities of a Class at a Given Revision
AuditQuery query = getAuditReader() .createQuery() .forEntitiesAtRevision(MyEntity.class, revisionNumber);
AuditEntity
factory class. The query below only selects entities where the name
property is equal to John
:
query.add(AuditEntity.property("name").eq("John"));
query.add(AuditEntity.property("address").eq(relatedEntityInstance)); // or query.add(AuditEntity.relatedId("address").eq(relatedEntityId));
List personsAtAddress = getAuditReader().createQuery() .forEntitiesAtRevision(Person.class, 12) .addOrder(AuditEntity.property("surname").desc()) .add(AuditEntity.relatedId("address").eq(addressId)) .setFirstResult(4) .setMaxResults(2) .getResultList();
Example 12.34. Query Revisions where Entities of a Given Class Changed
AuditQuery query = getAuditReader().createQuery() .forRevisionsOfEntity(MyEntity.class, false, true);
AuditEntity.revisionNumber()
- Specify constraints, projections and order on the revision number in which the audited entity was modified.
AuditEntity.revisionProperty(propertyName)
- Specify constraints, projections and order on a property of the revision entity, corresponding to the revision in which the audited entity was modified.
AuditEntity.revisionType()
- Provides accesses to the type of the revision (ADD, MOD, DEL).
MyEntity
class, with the entityId
ID has changed, after revision number 42:
Number revision = (Number) getAuditReader().createQuery() .forRevisionsOfEntity(MyEntity.class, false, true) .setProjection(AuditEntity.revisionNumber().min()) .add(AuditEntity.id().eq(entityId)) .add(AuditEntity.revisionNumber().gt(42)) .getSingleResult();
actualDate
for a given entity was larger than a given value, but as small as possible:
Number revision = (Number) getAuditReader().createQuery() .forRevisionsOfEntity(MyEntity.class, false, true) // We are only interested in the first revision .setProjection(AuditEntity.revisionNumber().min()) .add(AuditEntity.property("actualDate").minimize() .add(AuditEntity.property("actualDate").ge(givenDate)) .add(AuditEntity.id().eq(givenEntityId))) .getSingleResult();
minimize()
and maximize()
methods return a criteria, to which constraints can be added, which must be met by the entities with the maximized/minimized properties.
selectEntitiesOnly
- This parameter is only valid when an explicit projection is not set.If true, the result of the query will be a list of entities that changed at revisions satisfying the specified constraints.If false, the result will be a list of three element arrays. The first element will be the changed entity instance. The second will be an entity containing revision data. If no custom entity is used, this will be an instance of
DefaultRevisionEntity
. The third element array will be the type of the revision (ADD, MOD, DEL). selectDeletedEntities
- This parameter specified if revisions in which the entity was deleted should be included in the results. If true, the entities will have the revision type
DEL
, and all fields, except id, will have the valuenull
.
Example 12.35. Query Revisions of an Entity that Modified a Given Property
MyEntity
with a given id, where the actualDate
property has been changed.
AuditQuery query = getAuditReader().createQuery() .forRevisionsOfEntity(MyEntity.class, false, true) .add(AuditEntity.id().eq(id)); .add(AuditEntity.property("actualDate").hasChanged())
hasChanged
condition can be combined with additional criteria. The query below will return a horizontal slice for MyEntity
at the time the revisionNumber was generated. It will be limited to the revisions that modified prop1
, but not prop2
.
AuditQuery query = getAuditReader().createQuery() .forEntitiesAtRevision(MyEntity.class, revisionNumber) .add(AuditEntity.property("prop1").hasChanged()) .add(AuditEntity.property("prop2").hasNotChanged());
MyEntities
changed in revisionNumber with prop1
modified and prop2
untouched."
forEntitiesModifiedAtRevision
query:
AuditQuery query = getAuditReader().createQuery() .forEntitiesModifiedAtRevision(MyEntity.class, revisionNumber) .add(AuditEntity.property("prop1").hasChanged()) .add(AuditEntity.property("prop2").hasNotChanged());
Example 12.36. Query Entities Modified in a Given Revision
Set<Pair<String, Class>> modifiedEntityTypes = getAuditReader() .getCrossTypeRevisionChangesReader().findEntityTypes(revisionNumber);
org.hibernate.envers.CrossTypeRevisionChangesReader
:
List<Object> findEntities(Number)
- Returns snapshots of all audited entities changed (added, updated and removed) in a given revision.Executes
n+1
SQL queries, wheren
is a number of different entity classes modified within the specified revision. List<Object> findEntities(Number, RevisionType)
- Returns snapshots of all audited entities changed (added, updated or removed) in a given revision filtered by modification type. Executes
n+1
SQL queries, wheren
is a number of different entity classes modified within specified revision. Map<RevisionType, List<Object>> findEntitiesGroupByRevisionType(Number)
- Returns a map containing lists of entity snapshots grouped by modification operation (e.g. addition, update and removal). Executes
3n+1
SQL queries, wheren
is a number of different entity classes modified within specified revision.