Hibernate Envers'forEntitiesAtRevision'生成冗余子查询

问题描述 投票:0回答:1

我正在使用Hibernate Envers审核实体更改。实体和审计表存储在MySQL数据库中。该解决方案在大多数情况下都可以正常工作,但是我发现了一个很奇怪的问题。

假设我在某个修订版中具有实体状态,并且我希望获得该实体的先前更改。为此,我编写了以下方法:

    public <T> T getLastChange(@Nonnull Object id, @Nonnull Class<T> type, long beforeRev) {
        List<Number> revisions = AuditReaderFactory.get(entityManager).getRevisions(type, id);

        return revisions.stream()
                .map(Number::longValue)
                .filter(rev -> rev < beforeRev)
                .max(Comparator.comparingLong(rev -> rev))
                .map(rev -> AuditReaderFactory.get(entityManager).find(type, type.getName(), id, rev, true))
                .orElse(null);
    }

find生成“太安全”查询外,它工作正常:

select *
from persons_AUD person_aud0_
where person_aud0_.REV=(select max(person_aud1_.REV) from persons_AUD person_aud1_ where person_aud1_.REV<=462864 and person_aud0_.id=person_aud1_.id)
  and person_aud0_.id=56591;

我已经知道确切的修订版!如何避免此子查询??我只想要

select *
from persons_AUD person_aud0_
where person_aud0_.REV=462864
  and person_aud0_.id=56591;

当前,这会导致大表上出现硬性能问题。

将对我如何说服Envers使用通过的修订作为完全匹配的任何建议表示感谢。

hibernate hibernate-envers
1个回答
0
投票

我找到了解决问题的方法。AuditReader.find方法使用总是产生该子查询的forEntitiesAtRevision。但是经过一些实验,我注意到另一种方法forRevisionsOfEntity可以完全满足我的要求。所以我重写了我的查询,如下所示

    public <T> T getPreviousChange(@Nonnull Object id, @Nonnull Class<T> type, int beforeRev) {

        List resultList = getEntityManager().createQuery()
                .forRevisionsOfEntity(type, type.getName(), true, true)
                .add(AuditEntity.id().eq(id))
                .add(AuditEntity.revisionNumber().lt(beforeRev))
                .addOrder(AuditEntity.revisionNumber().desc())
                .setMaxResults(1).getResultList();

        return resultList.isEmpty() ? null : (T) resultList.get(0);
    }

现在,我得到一个查询,而不是2个:

select *
from persons_AUD person_aud0_ 
where person_aud0_.id=? and person_aud0_.REV<? 
order by person_aud0_.REV desc limit ?

即使在大桌子上也能表现出色。

P.S。AuditQuery构造函数实际上非常丰富和强大!以所需的方式修改查询很容易。谢谢。

© www.soinside.com 2019 - 2024. All rights reserved.