用envers列出每个实体的最新修订版

时间:2012-07-31 14:25:24

标签: java sql hibernate hibernate-envers

我正在尝试检索尚未删除的所有实体的最新版本。使用子选择在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 个答案:

答案 0 :(得分:7)

我们需要使用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();

另请参阅:

Find max revision of each entity less than or equal to given revision with envers

Can hibernate envers return the latest revision of all entities of a specific type?

答案 1 :(得分: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;
     }
  });

}

答案 2 :(得分:0)

尝试添加最大化的属性:

[your query].add(AuditEntity.revisionNumber().maximize())

答案 3 :(得分:0)

@charybr的答案是有效的,如果您正确选择了寄生虫的话。只需将要从中选择的子集所需的过滤器直接添加到最大化查询部分即可。 这样,select语句也将出现在子查询中。

"""Dear Sir or Madam,

I am writing to you about the show. I was very disappointed after the show. I would like to have my money back. First the show started at 10.15, and it should have started at 19.30.

After your show I wanted to visit my friends, and because of it, I couldn't do it.
"""

有点晚了,但可能会帮助别人。