使用 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/