java - JPA 可分页排序顺序区分大小写
问题描述
我正在使用 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);
奥迪表值为:apple,az,Ajay,Bala
。当我使用 asc 的排序顺序和排序字段名称进行搜索时,原始输出:Ajay,Bala,apple,az
。预期输出:Ajay,apple,az,Bala
.
我正在使用mysql数据库。表引擎 -Innodb,characterst-utf8,collate-utf8_bin.
请注意,它不是重复的问题。我没有得到这个问题的确切答案。在此先感谢。
解决方案
已编辑:正如严厉正确指出的那样,这需要在数据库级别使用正确的排序规则来解决。这很重要,因为您可能希望在排序列上有一个索引以获得最佳性能。
但是还有其他用例,它们可以将过滤与排序结合在一起,而不是纯列值,例如描述长度、列的总和或平均值等。出于这个原因,我包括一个 JPA 解决方案:
我最近为此苦苦挣扎,我担心 Pageable 接口不支持这个开箱即用。
解决方案是使用EntityManager
, CriteriaBuilder
,CriteriaQuery
并Specification
手动实现分页。您可以在此处找到解决方案。
您需要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() + "%")
);
}
推荐阅读
- javascript - 有没有办法在运行时将修改后的 SVG 设置为 Leafletjs 中的自定义图标?
- php - 在 php 中合并多个 doc 和 docx 文件
- sql - Oracle 11 SQL:将 1 行拆分为 x 行并插入一个新列
- google-api - 在大查询中使用火基分析创建图表
- python - Azure Functions - 无法在调用的脚本中导入其他 python 模块
- azure-functions - 使用 ServiceBusTrigger 在 Azure Function 中的 TelemetryInitializer 中访问 HttpContext
- search - 了解 GTFS 服务时间
- android - 按钮的 OnClick 事件并不总是有效
- object - 在内存块的开头放置一个小对象
- php - 如何修复 Mpdf overWrite() 不起作用?