10

我正在尝试检索尚未删除的所有实体的最新版本。使用子选择在 SQL 中执行此操作非常简单:

select * from article_aud aud1
where rev in
 (select max(rev) from article_aud aud2
  where aud1.id = aud2.id)
and revtype < 2

但我不知道如何通过 envers API 实现这一点。我从 AuditReader 开始,但没有找到选择不同对象的方法

public List<Object[]> findLatestArticleRevisions(){
    List<Object[]> results = (List<Object[]>) getJpaTemplate().execute(new AuditReaderCallback() {
        @Override
        public Object doInAuditReader(AuditReader auditReader) {
            return auditReader.createQuery().forRevisionsOfEntity(Article.class, false, false)
                // TODO select distinct on entities
                .addOrder(new PropertyAuditOrder(new RevisionNumberPropertyName(), false))
                .getResultList();
        }
    });

    return results;
}

重要:我想在一个或至少两个查询中执行此操作,因为我有很多文章(实体)有很多修订。

非常感谢!

4

4 回答 4

9

我们需要使用https://hibernate.atlassian.net/browse/HHH-7827的修复,即 AuditEntity.revisionNumber().maximize().computeAggregationInInstanceContext()。

    AuditQuery query = getAuditReader().createQuery().forRevisionsOfEntity(
            entityClass, false, false);
    query.add(AuditEntity.revisionNumber().le(revision));
    query.add(AuditEntity.revisionNumber().maximize()
            .computeAggregationInInstanceContext());
    query.addOrder(AuditEntity.revisionNumber().desc());
    return query.getResultList();

另请参阅:

使用 envers 查找小于或等于给定修订的每个实体的最大修订

hibernate envers 可以返回特定类型的所有实体的最新版本吗?

于 2014-09-11T10:55:59.033 回答
0

这将起作用:

    public <T extends AbstractPersistentEntity> Number latestRevision(final Class<T> entityClass,
        final long uniqueIdentifier) {
  return hibernateTemplate.execute(new HibernateCallback<Number>() {
     @Override
     public Number doInHibernate(Session session) throws HibernateException, SQLException {
        try {
           Number number = (Number) get(session).createQuery()
                    .forRevisionsOfEntity(entityClass, true, true)
                    .addProjection(AuditEntity.revisionNumber().max())
                    .add(AuditEntity.id().eq(uniqueIdentifier)).getSingleResult();
           if (number != null) {
              logger.debug("max_rev = %s for entity_class %s.%s", number,
                       entityClass.getSimpleName(), uniqueIdentifier);
           }
           return number;
        } catch (javax.persistence.NoResultException e) {
           logger.debug(
                    "unable to find revision number by[entity_class=%s,unique_identifier=%s]",
                    entityClass.getName(), uniqueIdentifier);
        }
        return null;
     }
  });

}

进而

    protected <T extends AbstractPersistentEntity> T loadForRevision(final Class<T> entityClass,
        final long uniqueIdentifier, final Number revisionNumber) {
  return (T) hibernateTemplate.execute(new HibernateCallback<Object>() {
     @Override
     public Object doInHibernate(Session session) throws HibernateException, SQLException {
        T result = get(session).find(entityClass, uniqueIdentifier, revisionNumber);
        return result;
     }
  });

}

于 2012-07-31T14:31:00.463 回答
0

尝试添加最大化属性:

[your query].add(AuditEntity.revisionNumber().maximize())
于 2012-08-01T06:05:59.120 回答
0

@charybr 的答案是有效的,如果你把 parathess 放在正确的地方。只需将要从中选择的子集直接添加到最大化查询部分所需的过滤器。这样,选择语句也将出现在子查询中。

    AuditQuery query = auditReader.createQuery()
            .forRevisionsOfEntity(Event.class, true, true);

    query.setFirstResult((pageable.getPageNumber()) * pageable.getPageSize());
    query.setMaxResults(pageable.getPageSize());
    query.add(
                AuditEntity.revisionNumber().maximize()
                .computeAggregationInInstanceContext()
                    .add(AuditEntity.property("critical").eq(true))
             );
    query.getResultList();

有点晚了,但可能会对某人有所帮助。

于 2020-01-29T10:39:23.060 回答