Return 对象的特定修订

Return a Specific Revision of An Object

我想让我的 Envers return 具有最高修订但仍低于给定修订编号的实体。

我想到的是:

@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)。它 return 对于 before 版本没有任何意义(这是正确的),它 return 对于 middle 版本仍然没有任何意义(不正确,现在实体存在!)然后returnafter 修订版(同样不正确,实体已被删除)。

当我们查看结果 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,然后什么都不选择,因为修订应该低于 2。

我似乎无法弄清楚如何修复查询,而且关于该主题的文档很少。我尝试删除 computeAggregationInInstanceCont(),但代码的行为方式没有任何变化。

获得低于用户定义值的最高修订的正确查询是什么?

您应该能够获取低于指定值的最高修订号,如下所示:

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();

这将按降序排列所有修订,returns 第一个条目。结果集中的行将用于具有主键 entityIdEntityClass 实体,并应用必须使用小于或等于提供的值的修订号对实体进行审计的限制。

这个问题归结为正确设置括号:

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;
    }
}