我正在使用Hibernate Envers来持久化对象历史记录。在某些时候,我们想要捕获对象图状态的快照 - 我们可以通过知道相应的Envers修订版来做到这一点,然后将其存储在审核记录中。
但是我们遇到了一个问题。在创建并存储其子审核记录(包括Envers修订版)的事务中,父对象被更新。我们可以获取最新的修订版:
或者创建一个新的版本:
我们正在使用Spring 3 @Transactional注解和Hibernate 4.2。
最小类图:
但是我们遇到了一个问题。在创建并存储其子审核记录(包括Envers修订版)的事务中,父对象被更新。我们可以获取最新的修订版:
Number revision = reader.getRevisionNumberForDate(new Date(Long.MAX_VALUE));
或者创建一个新的版本:
Number revision = reader.getCurrentRevision(DefaultRevisionEntity.class, true).getId();
您可以使用任一版本,但父级的提交总是在此之后发生。 这就是Envers增加修订版的时机。 因此,我们实际需要在审计记录中引用的修订版始终比存储的值高。 在最简单的情况下,我们获取并存储修订版N,但我们需要的父级版本存储为N + 1。
可以使用以下代码获取AuditReader阅读器引用:
JpaTransactionManager transactionManager; // injected
EntityManagerFactory emf = transactionManager.getEntityManagerFactory();
EntityManager entityManager = emf.createEntityManager();
AuditReader reader = AuditReaderFactory.get(entityManager);
我们正在使用Spring 3 @Transactional注解和Hibernate 4.2。
最小类图:
Parent.class
int version // for hibernate optimistic locking
String revisionName
List<AuditChild> audits
AuditChild.class
int enversRevision // use to retrieve previous graphs of parent
我尝试了多种方法来强制先提交父级,其中包括:
- 将代码分割成多个方法,并使用@Transactional(propagation = Propagation.REQUIRES_NEW)
- 显式调用entityManager.flush();
我尝试的所有方法都没有效果,或者会引起其他问题。如果有其他人成功的解决方案,我会非常高兴听到。谢谢。
reader.getCurrentRevision(DefaultRevisionEntity.class, true).getId()
不起作用吗?你需要引用当前事务的“当前”修订版本。 - adamwgetCurrentRevision()
返回的对象上的 Id 不是在提交当前 Tx 时应用的那个 Id。 我的解决方法是使用虚拟(-1)版本进行创建,并在第二个事务中读取并更新我的版本引用。 (环境:Hibernate Envers 4.2、Spring 3.2 的@Transactional 注释事务;DB2 9.1) - user598656