返回对象的特定修订版

时间:2017-12-04 12:00:57

标签: java hibernate hibernate-envers

我想让我的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(),但代码的行为方式没有变化。

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

2 个答案:

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