我正在使用规范使用JPA构建查询解决方案。
我使用Spring Data进行了如下排序和分页,并且使用Spring存储库样式方法进行查询。
//Building specification with parameters
MySpecification specification=new MySpecification(List<SearchParameters>);
//Setting sort order and pagination
Sort sortOrder = new Sort(Direction.ASC,"<field_to_sort>");
PageRequest pageRequest = PageRequest.of(pageIndex, pageSize, sortOrder);
repository.findAll(specification, pageRequest);
现在我可以根据 coalesce表达式对字段进行排序。 我了解spring数据Sort只能具有用于排序的属性名称,如上所示。
我尝试在JPA规范中设置排序顺序,但这也无济于事。
在坚持JPA规范的同时,是否可以将排序顺序设置为合并表达式?
任何帮助将不胜感激。
答案 0 :(得分:0)
从Spring Data 2.2开始,它仍然无法使用自己的类Sort
或Order
来调用SQL函数,这使得使用Specification
和从存储库编码中完全抽象变得更加困难。 >
有一种变通办法是仅将手工制作的Specification
用于排序目的,这将使用JPA的CriteriaBuilder
功能将排序设置为结果查询。
此类Specification
的示例(为了简洁起见,使用基于字符串的属性名称,也可以使用JPA元模型类):
public static Specification<Author> orderByPseudonymOrFullName() {
return (user, cq, cb) -> {
Expression<?> functionBasedAttributePath =
cb.lower(cb.coalesce(user.get("pseudonym"), user.get("fullName")));
Expression<Author> pathToUserId = user.get("id");
List<Order> orderByList = new ArrayList<>();
orderByList.add(cb.asc(functionBasedAttributePath));
// adding second sorting attribute to ensure stable order of users with same pseudonym
orderByList.add(cb.asc(pathToUserId));
cq.orderBy(orderByList);
Specification<Author> emptySpec = Specification.where(null);//empty no-op specification
return emptySpec.toPredicate(user, cq, cb);
};
}
然后像往常一样将其与Sort.unsorted()
一起使用,Spring Data不会将其考虑在内:
authorRepository.findAll(AuthorSpecifications.orderByPseudonymOrFullName(),
PageRequest.of(page, size, Sort.unsorted()));
通过包含测试以证明其有效的示例的示例链接到GitHub存储库:https://github.com/zzz3bra/customSortingWithSpringData
为什么起作用?
SimpleJpaRepository
类是默认的存储库实现,包含下一个相关的代码片段:
protected <S extends T> TypedQuery<S> getQuery(@Nullable Specification<S> spec, Class<S> domainClass, Sort sort) {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<S> query = builder.createQuery(domainClass);
Root<S> root = applySpecificationToCriteria(spec, domainClass, query);
query.select(root);
if (sort.isSorted()) {
query.orderBy(toOrders(sort, root, builder));
}
return applyRepositoryMethodMetadata(em.createQuery(query));
}
因此,如果sort
未排序,Spring Data将不会调用query
的{{1}}方法来覆盖orderBy
已设置的排序。