3

使用 Hibernate 的 Criteria api 进行排序和分页有一个很大的限制,它需要从数据库中检索不同的结果。api 提供的工具(如 DistinctRootTransformer)将不起作用,因为它是在从 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 数据库将返回类似的内容:

home_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 之后会启动。

4

2 回答 2

2

如果您以某种方法创建 DetachedCriteria 然后使用它,您可以尝试使用以下方法将 DetachedCriteria 转换为 Criteria:

DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Your.class);
// then add all your restrictions and convert
Criteria criteria = detachedCriteria.getExecutableCriteria(session);

然后应用你的分页

criteria.setFirstResult(pageable.getPage() * pageable.getSize());
criteria.setMaxResults(pageable.getSize());

然后执行标准。例如:

List<T> result = criteria.list();
于 2017-04-07T09:49:34.537 回答
1

当我需要分页时,我从不使用 DetachedCriteria,而是使用普通 Criteria,控制第一和最大结果。

从视图中,我确定我需要显示哪个页面,一旦我准备好标准,我就会以这种方式配置:

criteria.setMaxResults(lazyQuery.getPageSize());
criteria.setFirstResult(layQuery.getStart());

lazyQuery是我自己模型的一个对象,用于视图和业务逻辑。这很完美。

于 2015-11-12T11:17:03.063 回答