HIbernate Envers:修订的外键

时间:2018-09-25 16:11:26

标签: hibernate hibernate-envers

是否可以向实体的修订版本添加外键?

例如,如果我有实体Person

@Entity
@Audited
public class Person {
    @Id
    @Column
    private Integer idPerson;
    @Column
    private String favoriteHobby;
}

我想指出一个人的修订版本。假设我创建了一个年鉴,并且希望它包含该人当前最喜欢的爱好,但是如果该人以后会更新他/她的最爱,我希望该年鉴包含旧的爱好。

在SQL中,这可以通过创建包含列idPersonidRevisionidYearBook的表来实现。

但是我不确定是否以及如何将其转换为实体,进行查询,创建我的年鉴...而无需编写自定义查询或复制我的个人实体。

1 个答案:

答案 0 :(得分:0)

要首先通过评论回答您的问题,是的。

如果您将两个实体都标记为@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界面创建查询的所有其他方式。