Jav*_*tar 5 java spring hibernate spring-data-jpa jpa-criteria
我使用JPA CriteriaQuery构建我的动态Query并传入Spring Data Pageable对象:
sort=name,desc
Run Code Online (Sandbox Code Playgroud)
在后端,我的存储库中有一个方法来支持动态查询:
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;
}
Run Code Online (Sandbox Code Playgroud)
注意:我只为演示目的放了一个参数.
但是返回的数据是未排序的,因此我想问一下在CriteriaQuery中实现Pageable的任何方法.
小智 10
您可以从 spring 使用 QueryUtils 添加排序:
query.orderBy(QueryUtils.toOrders(pageable.getSort(), root, builder));
小智 7
Op 问题和 Angelo 的答案在现实生活中都不起作用。如果该表/查询返回数千条记录,则此方法将执行缓慢,并且您还可能会产生内存问题。
为什么?
两个结果集都会运行相同的查询两次,并在这些集合中维护完整的表/查询数据,只是为了进行计数或切片,当您需要在前端显示少量记录时,这没有任何意义。
我对 Spring Data 的建议是在存储库中扩展 JpaSpecificationExecutor 接口
@Repository
public interface UserRepository extends JpaRepository<User, Integer>,
JpaSpecificationExecutor {
}
Run Code Online (Sandbox Code Playgroud)
此接口将使您的存储库能够使用findAll(Specification, Pageable)方法。
之后,一切都很容易。您只需创建一个 Java 闭包即可将谓词注入到动态 jpa 查询中。
public Page<User> listUser( String name, int pageNumber, int pageSize ) {
Sort sort = Sort.by("id").ascending();
Pageable pageable = PageRequest.of(pageNumber, pageSize, sort);
return this.reservationRepository.findAll((root, query, builder) -> {
List<Predicate> predicates = new ArrayList<>();
if name!= null ) {
predicates.add(builder.equal(root.get("name"), name));
}
// More simple/complex conditions can be added to
// predicates collection if needed.
return builder.and(predicates.toArray(new Predicate[]{}));
}, pageable);
}
Run Code Online (Sandbox Code Playgroud)
正如您在此处看到的,该解决方案支持排序/过滤和数据库端分页。
在您的标准查询中,我看不到我会这样写的排序信息:
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);
List<Order> orders = new ArrayList<Order>(2);
orders.add(cb.asc(iRoot.get("name")));
orders.add(cb.asc(iRoot.get("desc")));
cq.orderBy(orders);
TypedQuery<User> query = em.createQuery(cq);
Page<User> result = new PageImpl<User>(query.getResultList(), page, totalRows);
return result;
Run Code Online (Sandbox Code Playgroud)
我没有测试它,但它应该工作
安杰洛
| 归档时间: |
|
| 查看次数: |
7584 次 |
| 最近记录: |