一尘不染

具有maxresults的休眠条件n + 1问题

hibernate

使用hibernate标准,我想选择一个对象,并将其与对象的oneToMany列表关联。我想通过此列表进行分页,避免出现可怕的hibernaten + 1选择问题

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

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语句(hurray)但无法处理分页的解决方案,即在父对象Mother(boo)上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();

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

有参加者吗?


阅读 239

收藏
2020-06-20

共1个答案

一尘不染

将其简化为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();

对于某些数据库,子选择获取children也可能有效。

2020-06-20