我有一个审计实体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?