【问题标题】:Listing latest revision of each entity with envers使用 envers 列出每个实体的最新版本
【发布时间】:2012-07-29 08:29:26
【问题描述】:

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

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

非常感谢!

【问题讨论】:

    标签: java sql hibernate hibernate-envers


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

      我们需要使用 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?

      【讨论】:

      • 有没有办法获取实体的最新版本号?假设插入了一个实体,更新了两次,现在它有 3 个修订号。如何获得最新的修订号?
      • 嗯,当我在查询中返回多个修订版时,这似乎有效,聚合函数为我提供了最新(最高)修订版。但如果只有一个修订版,则根本不返回任何修订版。你有过这个问题吗?
      • 实际上我认为误解了它的工作原理。如果您过滤掉实体的最新版本,则不会返回该实体。在过滤掉修订后,我想要最新版本的实体。 IE。在星期三之前给我所有的修订,并给我那个子集中的实体的最新版本。好像不行。
      【解决方案3】:

      尝试添加最大化属性:

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

      【讨论】:

      • 这只会给我最近更改的实体的修订版。我需要每个现有实体的最新版本
      • 嗯,你试过了吗?我认为它应该像问题一样生成一个带有 max() 子查询的查询。
      • 是的,我试过了。是的,它使用 max() 生成一个子查询,但子查询不是按 id 评估的,所以结果查询看起来像这样select * from article_aud aud1 where rev in (select max(rev) from article_aud aud2) id 比较缺失
      【解决方案4】:

      这将起作用:

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

      }

      【讨论】:

      • 感谢您的回答 - 但我想找到所有实体的最新版本,而不是特定实体。我没有要查询的 ID
      猜你喜欢
      • 1970-01-01
      • 2012-11-11
      • 2019-12-13
      • 1970-01-01
      • 2010-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多