2012-07-31 66 views
8

我試圖檢索所有實體的最新版本,這些實體尚未刪除。在SQL這樣做是非常簡單的與子查詢:使用envers列出每個實體的最新版本

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

重要:我想這樣做在一個或至少兩個查詢,因爲我有很多文章(實體)與許多修訂。

非常感謝!

回答

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?

+0

有沒有辦法獲得一個實體的最新版本號?說像插入一個實體,更新兩次,現在它有3個修訂號。我怎樣才能得到最新的修訂號碼? – AppSensei 2015-06-16 16:31:18

+0

嗯,這似乎工作時,我在查詢中返回多個修訂,聚合函數給了我最新(最高)的修訂。但是,如果只有一個版本,它根本不會返回任何版本。你有這個問題嗎? – chrismacp 2017-09-27 13:06:44

+0

其實我覺得誤解了它是如何工作的。如果過濾掉實體的最新版本,則不會返回該實體。我在過濾修訂版本後想要最新版本的實體。即星期三之前給我所有的修改,並給我最新版本的實體。似乎沒有這樣工作。 – chrismacp 2017-09-27 16:10:31

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

}

+0

謝謝您的回答 - 但我想找到的所有實體,而不是一個具體的最新版本。我沒有一個ID來查詢 – powerMicha 2012-07-31 14:35:13

0

嘗試添加最大化屬性:

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

這將只給我修改大多數新發變化的實體。我需要每個退出實體的最新修訂版 – powerMicha 2012-08-01 08:49:29

+0

嗯你試過了嗎?我認爲它應該用問題中的max()子查詢生成一個查詢。 – adamw 2012-08-02 08:56:30

+0

是的,我嘗試過。是的,它會生成一個帶有max()的子查詢,但是子查詢並不是按照id來計算的,所以得到的查詢看起來像這樣:'select * from article_aud aud1 where rev in(from article_aud aud2 select max(rev))'comparision由id缺失 – powerMicha 2012-08-02 11:30:22