休眠计数集合大小而不初始化

2022-09-01 02:32:38

有没有办法在不初始化的情况下计算关联集合的大小?

例如:

Select count(p.children) from Parent p

(有一个很好的理由,为什么我不能以任何其他方式做到这一点,因为我的where子句更复杂,而我的from子句是一个多态查询)

谢谢。


答案 1

除查询之外,其他可能的解决方案可能是映射(以 XML 表示法)。这样,您可以使用所需的任何查询获取 Parent,然后在不加载整个集合的情况下进行调用(仅执行类型查询)。childrenlazy="extra"parent.getChildren().size()SELECT COUNT

带有注释,它将是

@OneToMany
@org.hibernate.annotations.LazyCollection(
org.hibernate.annotations.LazyCollectionOption.EXTRA
)
private Set<Child> children = new HashSet<Child>();

更新:引用自 Java Persistence with Hibernate, ch. 13.1.3:

如果调用任何不是标识符 getter 方法的方法,则将初始化代理;如果开始循环访问其元素或调用任何集合管理操作(如 and ),则会初始化集合。休眠提供了一个额外的设置,该设置对大型集合非常有用。它们可以被映射为额外的懒惰。[...]size()contains()

[如上所述映射,] 如果调用 、 或 — 查询数据库以检索必要的信息,则集合将不再初始化。如果是 a 或 a,则操作并直接查询数据库。size()contains()isEmpty()MapListcontainsKey()get()

因此,使用如上所述映射的实体,您可以执行

Parent p = // execute query to load desired parent
// due to lazy loading, at this point p.children is a proxy object
int count = p.getChildren().size(); // the collection is not loaded, only its size

答案 2

您可以使用 Session#createFilter,它是一种显式操作集合的 HQL 形式。例如,您提到了父母和孩子,因此如果您有一个人p,则最基本的形式是:

session.createFilter( p.getChildren(), "" ).list()

这只会返回一个子项列表。重要的是要注意,返回的集合不是“实时的”,它与p没有任何关联。

有趣的部分来自第二个论点。这是一个 HQL 片段。例如,在这里,您可能需要:

session.createFilter( p.getChildren(), "select count(*)" ).uniqueResult();

您提到您有一个 where 子句,因此您可能还需要:

session.createFilter( p.getChildren(), "select count(*) where this.age > 18" ).uniqueResult();

请注意,没有 from 子句。也就是说,from 子句是从关联中隐含的。集合的元素被赋予别名“this”,因此您可以从HQL片段的其他部分引用它。


推荐