我正在使用Hibernate Envers来保存对象历史记录。在某些时候,我们想要捕获对象图状态的快照 - 我们可以通过了解相应的Envers修订来实现这一点,然后我们将其存储在审计记录中。
但是我们遇到了问题。父对象在我们创建和存储其子审计记录的同一事务中更新 - 完成Envers修订。我们可以获得最新版本:
Number revision = reader.getRevisionNumberForDate(new Date(Long.MAX_VALUE));
或创建新版本:
Number revision = reader.getCurrentRevision(DefaultRevisionEntity.class, true).getId();
并使用其中之一,但父之后的 commit 总是会发生。这就是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
我已经尝试了许多方法来强制父级的提交首先发生,其中包括:
我尝试的一切都没有效果或引起其他问题。我很高兴听到有效的解决方案。感谢。
答案 0 :(得分:0)
更简单的替代方法是使用@Version
。
首先,需要将Envers配置为实际审计乐观锁定字段的值,默认情况下不会这样做。您可以通过设置以下配置来执行此操作:
org.hibernate.envers.do_not_audit_optimistic_locking_field=false
此时,Envers将在审计历史记录表中包含该字段,并将分配的ORM版本值复制到审计历史记录表中。此时,我们有一种使用@Formula
将ORM实体行与审计历史记录行连接的独特方法。公式SQL将是:
SELECT e.REV
FROM YourEntity_AUD e
WHERE e.originalId.id = id
AND e.version = version
现在就像向实体添加字段一样简单:
@Formula( /* the SQL from above */)
@NotAudited
private Integer revisionNumber;
HTH。