首先回答 cmets 的问题,是的。
如果您将两个实体都标记为 @Audited,则您对任一实体所做的任何更改都会导致在该特定实体的审计架构中创建一个新的审计行。
AuditReader API 模仿了许多旧的传统 Hibernate Criteria API。您基本上可以根据已审核的实体类型构建任何查询,并应用大量条件来过滤结果。
这里我想提一个警告。
假设在一个事务中,我们创建了一个Person 并将它们放入YearBook:
final Session session = openSession();
try {
session.getTransaction().begin();
final Person person = new Person();
person.setName( "John Doe" );
person.setHobby( "Plays Guitar" );
session.save( person );
final YearBook yearBook = new YearBook();
yearBook.setYear( 2018 );
yearBook.getPeople().add( person );
session.save( yearBook );
session.getTransaction().commit();
}
catch( Exception ex ) {
if ( session.getTransaction().isActive() ) {
session.getTransaction().rollback();
}
throw ex;
}
finally {
session.close();
}
这意味着在审计架构中,将为这两种实体类型创建一个新的审计行,并且这些行将与相同的修订号相关联。为简单起见,假设是修订号 1。
在未来的交易中,您为此John Doe修改Person:
final Session session = openSession();
try {
session.getTransaction().begin();
final Person person = session.find( Person.class, personId );
person.setHobby( "Video Games" );
session.getTransaction().commit();
}
catch( Exception ex ) {
if ( session.getTransaction().isActive() ) {
session.getTransaction().rollback();
}
throw ex;
}
finally {
session.close();
}
此时:
-
YearBook 作为单个修订版,修订版 #1。
-
John Doe 的
Person 有两个修订版,修订版 #1 和 #2。
这里需要注意的是,针对修订版 1 的 YearBook 查询将永远不会在修订版 2 中返回有关 Person 的任何信息。这绝对是几乎所有情况下的预期结果;但是在某些特殊情况下,用户也希望 YearBook 触发修订。
如果您希望集合所有者在修改不影响集合本身状态的元素属性时也生成修订,您需要在容器上放置一个虚拟属性并将其作为一部分进行修改交易,以便双方都得到审计。
也就是说,您将如何获得 YearBook 的修订版?使用AuditReader API 非常简单:
final AuditReader reader = AuditReaderFactory.get( session );
// Get the revisions in ascending order from smallest to highest rev #
List<Number> revisions = reader
.forRevisionsOfEntity( YearBook.class, false )
.getResultList();
如果您已经知道感兴趣的修订号,则可以使用以下方法获取该实体的确切快照:
final AuditReader reader = AuditReaderFactory.get( session );
final YearBook yearBook = reader.find( YearBook.class, yearBookId, revision );
查看文档,了解使用 Envers 提供的 AuditReader 接口创建查询的所有其他方法。