6.5. 查询审计信息
6.5.1. 通过队列检索审计信息 复制链接链接已复制到粘贴板!
Hibernate Envers 提供通过查询检索审计信息的功能。
许多情况下,对审计数据的查询比 实时数据 的相应查询要慢得多,因为它们涉及关联的子选择。
通过给定修订版本查询类实体
此查询的入口点为:
AuditQuery query = getAuditReader()
.createQuery()
.forEntitiesAtRevision(MyEntity.class, revisionNumber);
然后,可以使用 AuditEntity 工厂类别指定限制。以下查询仅选择 name 属性等于 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();
查询修订,其中给定类的实体更改
此查询的入口点为:
AuditQuery query = getAuditReader().createQuery()
.forRevisionsOfEntity(MyEntity.class, false, true);
限制可以添加到此查询中,方式与上例相同。这个查询还有其它可能:
AuditEntity.revisionNumber()- 指定修改审计实体的修订版本号的限制、预测和顺序。
AuditEntity.revisionProperty(propertyName)- 指定修订实体属性的限制、预测和订单,对应于修改审计实体的修订版本。
AuditEntity.revisionType()- 提供对修订版本类型的访问(ADD、MOD、DEL)。
然后可以根据需要调整查询结果。以下查询选择 MyEntity 类的实体的最小修订号,其中的 entity Id ID 在修订号 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 值大于给定值的修订版本,但尽量小:
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();
mini ()和 属性的实体必须满足此条件。
max()方法 返回一个条件,可以向其中添加约束,但具有最大/最小
创建查询时传递两个布尔值参数:
selectEntitiesOnly-
这个参数只有在未设置显式投射时才有效。
如果为true,则查询的结果将是满足指定限制修订版本时更改的实体列表。
若为 false,则结果将是三个元素数组的列表。第一个元素是更改后的实体实例。第二个是包含修订数据的实体。如果不使用自定义实体,这将是DefaultRevisionEntity实例。第三个元素数组将是修订的类型(ADD、MOD、DEL)。 selectDeletedEntities-
此参数指定是否必须将删除实体的修订包含在结果中。如果为 true,实体将具有修订类型
DEL,除 id 外的所有字段都将值为null。
查询修改后属性的实体的修订
以下查询将返回 MyEntity 及给定 ID 的所有修订,其中的 actualDate 属性已更改。
AuditQuery query = getAuditReader().createQuery()
.forRevisionsOfEntity(MyEntity.class, false, true)
.add(AuditEntity.id().eq(id));
.add(AuditEntity.property("actualDate").hasChanged())
hasChanged 条件可以和附加标准组合。以下查询将在生成 revisionNumber 时为 MyEntity 返回一个横向片段。它仅限于修改 prop1 但不修改 prop 2 的修订版本。
AuditQuery query = getAuditReader().createQuery()
.forEntitiesAtRevision(MyEntity.class, revisionNumber)
.add(AuditEntity.property("prop1").hasChanged())
.add(AuditEntity.property("prop2").hasNotChanged());
结果集还包含数字低于 revisionNumber 的修订版本。这意味着,这个查询无法读取为"通过 prop1 修改和 prop 2 不更改的 revisionNumber 中所有 MyEntities 更改"。
以下查询显示如何使用 forEntitiesModifiedAtRevision 查询返回这个结果:
AuditQuery query = getAuditReader().createQuery()
.forEntitiesModifiedAtRevision(MyEntity.class, revisionNumber)
.add(AuditEntity.property("prop1").hasChanged())
.add(AuditEntity.property("prop2").hasNotChanged());
在给定修订版本中修改查询实体
以下示例显示了给定修订中修改的实体的基本查询。它允许检索指定修订中更改的实体名称和对应 Java 类:
Set<Pair<String, Class>> modifiedEntityTypes = getAuditReader()
.getCrossTypeRevisionChangesReader().findEntityTypes(revisionNumber);
还可以从 org.hibernate.envers.CrossTypeRevisionChangesReader 访问许多其他查询:
list<Object> findEntities(Number)-
返回给定修订中更改(添加、更新和删除)的所有审计实体的快照。执行
n+1SQL 查询,其中n是指定修订版本中修改的多个不同实体类。 List<Object> findEntities(Number, RevisionType)-
返回给定修订版本中更改(添加、更新或删除)的所有审计实体的快照,并按照修改类型过滤。执行
n+1SQL 查询,其中n是指定修订版本中修改的多个不同实体类。Map<RevisionType, List<Object>> findEntitiesGroupByRevisionType(Number)-
返回包含由修改操作分组的实体快照列表的映射,如添加、更新或删除。执行
3n+1SQL 查询,其中n是指定修订版本中修改的多个不同实体类。