Hibernate计数集合大小而不初始化

时间:2010-05-26 13:04:59

标签: java hibernate lazy-loading

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

e.g。

Select count(p.children) from Parent p

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

感谢。

3 个答案:

答案 0 :(得分:58)

除查询之外的可能解决方案可能是将childrenlazy="extra"映射(以XML表示法)。这样,您可以使用您需要的任何查询来获取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,ch。 13.1.3:

  

如果您调用任何非标识符getter的方法,则会初始化代理   方法,如果您开始迭代其元素或if,则初始化集合   您可以调用任何集合管理操作,例如size()contains()。   Hibernate提供了一个额外的设置,主要用于大型集合;它们可以映射为 extra lazy 。 [...]

     

[如上所述],如果您调用size()contains()isEmpty(),则不再初始化该集合 - 将查询数据库以检索必要的信息。如果是MapList,则操作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

答案 1 :(得分:1)

您可以使用Session#createFilter,这是一种明确对集合进行操作的HQL形式。例如,你提到父母和孩子,所以如果你有一个人,那么最基本的形式是:

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片段的其他部分引用它。

答案 2 :(得分:-2)

您可以这样做:

@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(),如果懒惰的初始化列表,您将获得大小,而无需获取列表本身。