2013-02-07 78 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。它有更快的读取速度,但写入速度更慢。