我正在使用JpaRepository Pageable查询进行分页。除了排序字段区分大小写的问题之外,所有其他东西都工作正常。以下查询用于获取列表。
Pageable pageable = null;
if (paginationRequestDTO.getSortOrder().equalsIgnoreCase("desc"))
pageable = new PageRequest(page, size, Sort.Direction.DESC, sortfiled);
else
pageable = new PageRequest(page, size, Sort.Direction.ASC, sortfiled);
Page<Audi> audiPage = null;
audiencePage = audiRepository.search(paginationRequestDTO.getSearchKey(), pageable);
Audi表的值为:apple,az,Ajay,Bala
。
当我使用asc的sortorder搜索并排序字段名称时,
原始输出:Ajay,Bala,apple,az
。
预期输出:Ajay,apple,az,Bala
。
我正在使用mysql数据库。表引擎-Innodb,characterst-utf8,collate-utf8_bin.
请注意,它不是重复的问题。对于此问题,我没有得到确切的答案。
答案 0 :(得分:-1)
已编辑:正如harsh正确指出的那样,这需要使用正确的排序规则在数据库级别解决。这很重要,因为您可能希望在sort列上有一个索引以获得最佳性能。
但是,还有其他一些用例,它们可以将过滤与其他排序组合在一起,而不是纯列值,例如根据描述的长度,列的总和或平均值等。因此,我包括一个JPA解决方案:
最近我为此感到挣扎,但恐怕Pageable界面不支持此功能。
解决方案是使用EntityManager
,CriteriaBuilder
,CriteriaQuery
,Specification
并手动实现分页。您可以找到解决方案here。
您需要手动构造Page
对象:
public Page<Audi> getPage(int pageNumber, int pageSize, String descriptionFilter, Sorting sorting) {
return new PageImpl<>(
getPageItems(pageNumber, pageSize, descriptionFilter, sorting),
PageRequest.of(pageNumber, pageSize, Sort.by(Sort.Direction.ASC, sorting.name())),
getTotalCount(descriptionFilter)
);
}
getPageItems
使用LIMIT
和OFFSET
private List<Audi> getPageItems(int pageNumber, int pageSize, String descriptionFilter, Sorting sorting) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Audi> query = cb.createQuery(Audi.class);
Root<Audi> root = query.from(Audi.class);
query.where(createSpecification(descriptionFilter).toPredicate(root, query, cb));
if (sorting.equals(Sorting.descriptionCaseInsensitive)) {
query.orderBy(cb.asc(cb.lower(root.get("description"))));
} else {
throw new UnsupportedOperationException("Unsupported sorting: " + sorting.name());
}
query.select(root);
return em.createQuery(query)
.setFirstResult(pageNumber * pageSize)
.setMaxResults(pageSize)
.getResultList();
}
getTotalCount
选择count(distinct(*))
,
private long getTotalCount(String descriptionFilter) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Long> query = cb.createQuery(Long.class);
Root<Audi> root = query.from(Audi.class);
query.where(createSpecification(descriptionFilter).toPredicate(root, query, cb));
query.select(cb.countDistinct(root));
// getSingleResult can return null, if no rows fulfill the predicate
return Optional.ofNullable(em.createQuery(query).getSingleResult()).orElse(0L);
}
两者都重复使用相同的谓词,从而过滤行:
private Specification<Audi> createSpecification(String descriptionFilter) {
return Specification.where(
(root, query, criteriaBuilder) ->
criteriaBuilder.like(criteriaBuilder.lower(root.get("description")), "%" + descriptionFilter.toLowerCase() + "%")
);
}