我有一個審計實體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?