我正在将遗留的iBatis实现转换为Hibernate,出于向后兼容的目的,需要提供对象集合的计数而不是集合本身。原始查询是:
select A.*, ( select count(*) from B where B.A_id = A.id ) as B_count from A;
和b_count将显示在回复中。我希望能够做同样的事情,而不会为每个查询结果延迟加载A的B集合。
有任何想法或建议吗?
答案 0 :(得分:2)
最好的方法似乎是使用Hibernate公式,映射到A类中我的BCount属性的getter和setter。我的代码:
public class A {
// ...
private long bCount;
// ...
@Formula( "(select count(*) from B where B.A_id = id" )
public long getBCount() {
return this.bCount;
}
public void setBCount( long bCount ) {
this.bCount = bCount;
}
}
关于这个方法的好处是,计数在同一个fetch中返回以包含初始对象,并且不会导致1 + N查询收集查询结果!
答案 1 :(得分:0)
您可以使用投影。
行计数的语法如下:
Criteria crit = session.createCriteria(B.class);
crit.setProjection(Projections.rowCount());
List results = crit.list();
编辑:重新阅读后,我认为这可能不是你所要求的......
答案 2 :(得分:0)
Hibernate过滤器用于对查询结果应用其他限制(例如将它们视为“where”子句的一部分),因此它们不会执行您想要的操作。你有两个选择:
A)你可以急切地为你的A收集Bs:
from A a left join fetch a.Bs b如果你这样做,请记住,对于会返回多个的查询,因为你可能会在结果列表中得到重复项(例如,如果你有2个As,并且每个都有3个B,那么你将得到6个结果)。将它们包裹在一套以确保独特性。
B)假设您有适当的A构造函数,您可以执行以下操作:
select new A(a.field1, a.field2, ... a.fieldN, count(*) as B_count) from A a left join a.Bs b group by a.field1, a.field2, ... a.fieldN