我想让我的Envers返回仍然低于给定修订号的最高版本的实体。
我想出的是以下内容:
@PersistenceContext
private EntityManager em;
@Test
public void test() throws Exception {
final Number before = AuditReaderFactory.get(this.em).getRevisionNumberForDate(new Date(Long.MAX_VALUE));
final UserEntity user = new UserEntity().loginName("one");
doInTransaction(() -> this.em.persist(user));
final Number middle = AuditReaderFactory.get(this.em).getRevisionNumberForDate(new Date(Long.MAX_VALUE));
user.setLoginName("two");
doInTransaction(() -> this.em.persist(user));
final Number after = AuditReaderFactory.get(this.em).getRevisionNumberForDate(new Date(Long.MAX_VALUE));
Assert.assertEquals(new ArrayList<>(), getRevisions(before));
Assert.assertEquals(Arrays.asList(user), getRevisions(middle));
Assert.assertEquals(new ArrayList<>(), getRevisions(after));
}
private void doInTransaction(Runnable magic) {
try {
this.em.getTransaction().begin();
magic.run();
this.em.getTransaction().commit();
} catch (final Exception e) {
this.em.getTransaction().rollback();
throw new RuntimeException(e);
}
}
private List<UserEntity> getRevisions(Number revisionNumber) {
final AuditReader auditReader = AuditReaderFactory.get(this.em);
try {
return auditReader.createQuery().forRevisionsOfEntity(UserEntity.class, true, false)
.add(AuditEntity.revisionNumber().maximize().computeAggregationInInstanceContext()) // the highest revision possible
.add(AuditEntity.revisionNumber().le(revisionNumber)) // as long as the revision is below or equal to revisionNumber
.getResultList();
} catch (final NoResultException e) {
return null;
}
}
不起作用的方法是getRevisions(Object, Number)
。它没有为before
修订版返回任何内容(这是正确的),它仍然没有返回middle
修订版(不正确,现在实体存在!)然后返回after
修订版的内容(也不正确,该实体已被删除)。
当我们查看生成的SQL时,这种行为的原因很明显:
SELECT * from user_aud u
WHERE u.REV = (
SELECT MAX (v.REV)
FROM user_aud v
WHERE v.id=u.id
)
AND u.REV <= ? ORDER BY u.REV asc
u.REV <= ?
部分应该在内部查询中。它现在生成的方式Hibernate决定最大修订版为3,然后不选择任何内容,因为rev应该低于2.
我似乎无法弄清楚如何修复查询,而且关于这个主题的文档很少。我尝试删除computeAggregationInInstanceCont()
,但代码的行为方式没有变化。
获得最高版本低于用户定义值的正确查询是什么?
答案 0 :(得分:1)
您应该能够获得低于指定值的最高版本号,如下所示:
AuditReaderFactory.get( session )
.createQuery()
.forRevisionsOfEntity( EntityClass.class, true, true )
.addOrder( AuditEntity.revisionNumber().desc() )
.add( AuditEntity.id().eq( entityId ) )
.add( AuditEntity.revisionNumber().le( userSuppliedValue ) )
.setMaxResults( 1 )
.singleResult();
这将按降序排序所有修订并返回第一个条目。结果集中的行将用于具有主键EntityClass
的{{1}}实体,并应用必须审核实体的限制,其修订号小于或等于提供的值。
答案 1 :(得分:1)
此问题归结为正确设置括号:
private List<UserEntity> getRevisions(Number revisionNumber) {
final AuditReader auditReader = AuditReaderFactory.get(this.em);
try {
return auditReader.createQuery().forRevisionsOfEntity(UserEntity.class, true, false)
.add(AuditEntity.revisionNumber().maximize().computeAggregationInInstanceContext().add(AuditEntity.revisionNumber().le(revisionNumber)))
.getResultList();
} catch (final NoResultException e) {
return null;
}
}