我正在尝试使用基于行的限制(例如:setFirstResult(5)
和setMaxResults(10)
)在已连接到其他表的Hibernate Criteria查询上实现分页.
可以理解的是,数据随机被切断; 这里解释了原因.
作为解决方案,页面建议使用"第二个sql选择"而不是连接.
如何将现有条件查询(使用连接createAlias()
)转换为使用嵌套选择?
您可以通过请求不同的ID列表而不是不同的水合对象列表来实现所需的结果.
只需将其添加到您的标准:
criteria.setProjection(Projections.distinct(Projections.property("id")));
现在,您将根据基于行的限制获得正确数量的结果.这样做的原因是因为投影将执行清晰度检查作为 sql查询的一部分,而不是ResultTransformer 在执行sql查询后过滤清除结果的结果.
值得注意的是,您现在将获得一个id列表,而不是获取对象列表,您可以使用这些ID来稍后从休眠中对对象进行水合.
我正在使用我的代码.
只需将其添加到您的标准:
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
该代码将类似于本机sql的select distinct*from table.希望这个有所帮助.
根据FishBoy的建议略有改进.
可以在一次点击中进行这种查询,而不是在两个单独的阶段中进行.即,下面的单个查询将正确地分页不同的结果,并且还返回实体而不仅仅是ID.
只需使用带有id投影的DetachedCriteria作为子查询,然后在主Criteria对象上添加分页值.
它看起来像这样:
DetachedCriteria idsOnlyCriteria = DetachedCriteria.forClass(MyClass.class); //add other joins and query params here idsOnlyCriteria.setProjection(Projections.distinct(Projections.id())); Criteria criteria = getSession().createCriteria(myClass); criteria.add(Subqueries.propertyIn("id", idsOnlyCriteria)); criteria.setFirstResult(0).setMaxResults(50); return criteria.list();
@ FishBoy建议的一个小改进是使用id投影,因此您不必对标识符属性名称进行硬编码.
criteria.setProjection(Projections.distinct(Projections.id()));