【发布时间】:2016-02-13 16:41:44
【问题描述】:
使用 Hibernate 的 Criteria api 进行排序和分页有一个很大的限制,它需要从数据库中检索不同的结果。像 DistinctRootTransformer 这样的 api 提供的工具将不起作用,因为它是在 从 db 检索实体之后应用的,因此会中断分页和排序。获得具有关联限制的查询的不同结果的唯一方法是通过 DetachedCriteria 限制结果集:
DetachedCriteria dc = DetachedCriteria.forClass(Household.class, "h")
.createAlias("cats", "c", JoinType.LEFT_OUTER_JOIN)
.add(Restrictions.or(
Restrictions.isEmpty("cats"),
Restrictions.ne("c.name", "Sylvester")
))
.setProjection(Projections.distinct(Projections.property("h.id")));
Criteria criteria = session.createCriteria(Household.class)
.add(Property.forName("id").in(dc));
...apply paging, sorting and filtering to criteria.
有没有人知道更好的方法,例如省略子查询并使用连接而不破坏分页?我的目标是找到一个可重用的解决方案,例如只将一个标准传递给另一个应用分页、排序和过滤的方法。
更新:
以下代码不起作用。由于加入,我必须使用 Resulttransformer,以获得不同的结果。但是,它是在排序和分页之后应用的。
Criteria criteria = session.createCriteria(Household.class)
.createAlias("cats", "c", JoinType.LEFT_OUTER_JOIN)
.add(Restrictions.ne("c.name","Sylvester"))
.setFirstResult((page - 1) * pagesize)
.setMaxResults(pagesize)
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
例如调试 sql 数据库会返回类似的内容:
household_id=1,...cat_ids={1,2};household_id=1,...cat_ids={1,2};household_id=2,...cat_ids={1};
在此示例中,将 pagesize 设置为 1 并查看页面 2 应该返回 uid 2,因为只有两个不同的用户。但正如您在数据库输出中看到的那样,它返回了错误的 uid 1,因为 Resulttransformers 之后会启动。
【问题讨论】:
-
如何将排序应用于您的标准?为了确保页面之间没有重复,我相信您必须强制执行总排序。可以对分离的条件进行排序,但您将其投影为仅一个 ID,因此您只能按 ID 排序。考虑示例:获取目录中 150 件蓝色衬衫的第 1 页尺寸 50 件蓝色衬衫,按价格升序排序;当用户请求第 2 页时,所有内容都应该是看不见的并且更昂贵,对吧?如何保证? (假设需要连接的衬衫如面料、收藏等存在一对多关系。)
标签: java hibernate sorting hibernate-criteria data-paging