我使用JPA CriteriaQuery来构建我的动态查询,并传入一个Spring Data Pageable对象:
sort=name,desc
在后端,我的Repository中有一个支持动态查询的方法:
public Page<User> findByCriteria(String username, Pageable page) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<User> cq = cb.createQuery(User.class);
Root<User> iRoot = cq.from(User.class);
List<Predicate> predicates = new ArrayList<Predicate>();
if (StringUtils.isNotEmpty(username)) {
predicates.add(cb.like(cb.lower(iRoot.<String>get("username")), "%" + username.toLowerCase() + "%"));
}
Predicate[] predArray = new Predicate[predicates.size()];
predicates.toArray(predArray);
cq.where(predArray);
TypedQuery<User> query = em.createQuery(cq);
int totalRows = query.getResultList().size();
query.setFirstResult(page.getPageNumber() * page.getPageSize());
query.setMaxResults(page.getPageSize());
Page<User> result = new PageImpl<User>(query.getResultList(), page, totalRows);
return result;
}
注意:我只放了一个参数用于演示。
然而,返回的数据是未排序的,因此我想问的是,任何方式来实现在CriteriaQuery中的Pageable。
5条答案
按热度按时间ncecgwcz1#
您可以使用spring中的QueryUtils添加排序:
query.orderBy(QueryUtils.toOrders(pageable.getSort(), root, builder));
wn9m85ua2#
在您的条件查询中,我没有看到排序信息,我将以这种方式编写:
我没有测试过,但应该可以用
安杰洛
eqzww0vc3#
Op问题和Angelo的答案在现实场景中都不起作用。如果表/查询返回数千条记录,这种方法执行起来会很慢,而且还可能产生内存问题。
为什么?
两个结果集将运行相同的查询两次,并在这些集合中保留完整的表/查询数据,只是为了计数或切片,当您需要在前端显示很少的记录时,这是没有意义的。
我对SpringData的建议是在存储库中扩展JpaSpecificationExecutor接口
此接口将使您的存储库能够使用**findAll(Specification,Pageable)**方法。
在那之后,一切都相当容易,您只需要创建一个Java闭包来将 predicate 注入到动态jpa查询中。
如您所见,此解决方案支持排序/筛选和数据库端分页。
ffscu2ro4#
使用
JpaSpecificationExecutor
并将其封装在类中的完整示例:首先将存储库定义为
SomeEntity
的JpaRepository和JpaSpecificationExecutor的扩展:}
按条件查找类:
}
调用简单调用:
vxf3dgd45#