2013-02-07 74 views
0

我有一個審計實體A.實體A保存字段「名稱」和實體B的集合(註釋爲多對多關係)。我創建了A的實例,定義了名稱,實體B的集合並將其全部保存到數據庫中。這是修訂#1。然後我更改了A的名稱並在DB中更新它。這是修訂#2。 我用下面的方法來獲得A級的所有實體在修改#2Envers @ManyToMany子查詢

List<A> list = getAuditReader().createQuery().forEntitiesAtRevision(A.class, 2) 
    .add(AuditEntity.revisionNumber().eq((int) revisionId)).getResultList(); 

我得到實體A修訂版#2,但Envers也取從版本#1與此相關的一個實體B的集合。這裏由Envers用於查詢的例子:

SELECT a_b_aud.a_id, a_b_aud.b_id 
FROM a_b_aud CROSS JOIN b_aud 
WHERE a_b_aud.b_id=b_aud.id 
     AND b_aud.rev=(SELECT max(b_aud2.rev)) FROM b_aud AS b_aud2 WHERE b_aud2.rev<=2 AND b_aud.id=b_aud2.id) 
     AND a_b_aud.rev=(SELECT max(a_b_aud2.rev)) FROM a_b_aud AS a_b_aud2 WHERE a_b_aud2.rev<=2 AND a_b_aud.a_id=a_b_aud2.a_id AND a_b_aud.b_id=a_b_aud2.b_id) 

但其實我的情況下,需要NULL作爲實體B的集合修訂版#2(因爲性能問題)的有沒有它的變化。

此查詢中有兩個子查詢。如果我們有多個與A(C,D,E,F)相關的實體集合,並且每個b_aud和a_b_aud有大約10萬行,上面的查詢需要很長時間。 我定義爲不審計(即沒有添加@Audited註釋入B)和定義由下述A B關係實體B:

@ManyToMany 
@Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE}) 
@JoinTable(name = "a_b", joinColumns = @JoinColumn(name = a_id)) 
@Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED) 
public Set<B> getBs(); 

它修復第一子選擇。 但我找不到標準的解決方案,如果它不存在請求的修訂(在我的情況#2),不查詢B的。因此,查詢應該是這樣的:

SELECT a_b_aud.a_id, a_b_aud.b_id 
FROM a_b_aud CROSS JOIN b_aud 
WHERE a_b_aud.b_id=b_aud.id b_aud.rev=2 AND a_b_aud.rev=2 

我發現使用原生SQL查詢和使用Hibernate模板來執行它的唯一解決方案。然後使用ResultTransformer將結果值轉換爲實體A.

有人可以幫助解決這個問題嗎?是否有需要添加的標準配置/註釋以避免第二個SUBSELECT?

回答

0

Envers在請求時不會加載相關實體。不過,B實體總是總是延遲加載(無論關係上的註釋),所以如果你不想執行加載它們的查詢,只是不要訪問該字段。

如果您想要更好地閱讀績效,您可能還想看看有效性審計策略,請參閱http://docs.jboss.org/hibernate/core/4.1/devguide/en-US/html/ch15.html#d5e4085。它有更快的讀取速度,但寫入速度更慢。