例如:
Select count(p.children) from Parent p
(由于我的where子句更复杂,并且我的from子句是一个多态查询,所以我不能以其他方式完成这个任务)
谢谢。
Select count(p.children) from Parent p
(由于我的where子句更复杂,并且我的from子句是一个多态查询,所以我不能以其他方式完成这个任务)
谢谢。
除了查询之外,可能的解决方案是使用 lazy="extra"
(在XML符号中)映射children
。这样,您可以使用任何需要的查询获取Parent,然后调用 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》第13.1.3章的引用:
如果您调用的任何方法不是标识符getter方法,则代理将被初始化;如果您开始遍历其元素或调用任何集合管理操作(例如
size()
和contains()
),则集合将被初始化。Hibernate提供了一个额外的设置,对于大型集合非常有用;它们可以映射为extra lazy. [...][如上所述映射],如果您调用
size()
、contains()
或isEmpty()
,则不再初始化集合——会查询数据库以检索必要的信息。如果它是Map
或List
,则containsKey()
和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
isEmpty()
,Hibernate 不应该运行 COUNT(*)
查询。另请参阅:https://blog.jooq.org/2016/09/14/avoid-using-count-in-sql-when-you-could-use-exists/ - Lukas EderCOUNT
被执行是因为 Hibernate 缓存了集合大小,这样 collection.isEmpty()
和 collection.size()
都使用 cachedSize
而不是总是执行 COUNT(*)
。但是,你关于 collection.isEmpty()
的想法是正确的,可以使用 EXISTS 代替。但是,EXTRA_LAZY
也不是真正的性能优化(我认为它更像是代码异味),因为如果你有一个非常大的集合,最好避免使用集合,而是使用分页查询。 - Vlad Mihalceasession.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片段的其他部分引用它。
@Override
public FaqQuestions getFaqQuestionById(Long questionId) {
session = sessionFactory.openSession();
tx = session.beginTransaction();
FaqQuestions faqQuestions = null;
try {
faqQuestions = (FaqQuestions) session.get(FaqQuestions.class,
questionId);
Hibernate.initialize(faqQuestions.getFaqAnswers());
tx.commit();
faqQuestions.getFaqAnswers().size();
} finally {
session.close();
}
return faqQuestions;
}
在您的控制器中使用faqQuestions.getFaqAnswers().size(),您将获得懒加载列表的大小,而无需获取列表本身。