I have an audited entity A. Entity A holds field 'name' and a collection of entities B (annotated as Many-to-many relationship). I created an instance of A, defined name, collection of entities B and save all it into DB. This is revision #1. Then I changed name of A and update it in DB. This is revision #2.
I use the following method to get all entities of class A at revision #2
List<A> list = getAuditReader().createQuery().forEntitiesAtRevision(A.class, 2)
.add(AuditEntity.revisionNumber().eq((int) revisionId)).getResultList();
I get entity A at revision #2, but Envers also fetches collection of entities B related to this A from revision #1. Here an example of query used by 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)
But actually I need NULL as a collection of entities B in case of there were no changes for it at revision #2 (because of performance issue).
There are two subselects in this query. And if we have more then one collection of entities related to A (C, D, E, F) and for about 100 thousands rows for each b_aud and a_b_aud the query above takes a lot of time.
I defined entity B as not audited (i.e. did not add @Audited annotation into B) and defined A B relation by the following:
@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();
It fixes first SUBSELECT.
But I can not find standard solution to not query B's if it do not exist for requested revision (in my case #2). So the query should look like:
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
The only solution I found is using native sql query and to execute it using hibernate template. Then convert result values into entity A using ResultTransformer.
Could anybody help with this issue? Is there a standard configuration/annotation I need to add to avoid second SUBSELECT?