hibernate 标准 n+1 问题与 maxresults

标签 hibernate criteria

使用 hibernate ctiteria 我想选择一个对象,它与对象的 oneToMany 列表相关联。我想通过这个列表分页避免可怕的 hibernate n+1 选择问题

这是一个有效的解决方案,它需要 11 次访问 10 个父对象的数据库。

Criteria criteria = this.getSession().createCriteria(Mother.class);
criteria.addOrder(Order.asc("title"))
.setMaxResults(details.getMaxRows())
.setFirstResult(details.getStartResult())
.setFetchMode("kittens", FetchMode.SELECT);
List test = criteria.list();

这是一个仅执行一个 sql 语句(欢呼)但无法处理分页的解决方案,即父对象 Mother 上的 setMaxResults 和 setFirstResult 不正确(嘘)
Criteria criteria = this.getSession().createCriteria(Mother.class);
criteria.addOrder(Order.asc("title"))
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
.setMaxResults(details.getMaxRows())
.setFirstResult(details.getStartResult())
.setFetchMode("kittens", FetchMode.JOIN);
List test = criteria.list();

这似乎是一个常见的要求,但我已经寻找了一个没有运气的解决方案。

有接类人吗?

最佳答案

将其缩减为 1 个查询很困难(即我不知道可移植的解决方案),但将其缩减为 2 个查询(不考虑 n)非常简单:

Criteria criteria = this.getSession().createCriteria(Mother.class);
criteria.addOrder(Order.asc("title"))
    .setMaxResults(details.getMaxRows())
    .setFirstResult(details.getStartResult())
    .setProjection(Projections.id());
List<?> ids = criteria.list();

criteria = getSession().createCriteria(Mother.class)
    .add(Restrictions.in("id", ids))
    .setFetchMode("children", FetchMode.JOIN)
    .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)

return criteria.list();

对于某些数据库,subselect fetching children也可能有用。

关于 hibernate 标准 n+1 问题与 maxresults,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5567754/

相关文章:

java - Hibernate 键多对一

java - 将一个 DAO 的方法用于另一个

java - hibernate.cfg.xml 在源文件中但仍未找到

grails - 当hasMany没有任何元素时,选择Grails条件

c# - 如何查询在 NHibernate 中存储为枚举的标志

java - 如何使用 JPA CriteriaBuilder selectCase() 以便它可以将 Predicate 作为结果?

hibernate - 使用 spring boot 和 cloud foundry 将 Redis 集成为非平台 oracle 数据库的 Hibernate 二级缓存

java - Spring 5 - 在 HQL 中使用未知 SQL 函数

hibernate - 如何创建 Grails 域对象但不保存?

mysql - 推进/Symfony 1.4 : combine securely custom sql subquery with criteria