JPA Pageable排序顺序区分大小写

时间:2018-11-09 13:52:40

标签: java spring-data-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);

Audi表的值为:apple,az,Ajay,Bala。 当我使用asc的sortorder搜索并排序字段名称时, 原始输出:Ajay,Bala,apple,az。 预期输出:Ajay,apple,az,Bala

我正在使用mysql数据库。表引擎-Innodb,characterst-utf8,collate-utf8_bin.

请注意,它不是重复的问题。对于此问题,我没有得到确切的答案。

1 个答案:

答案 0 :(得分:-1)

已编辑:正如harsh正确指出的那样,这需要使用正确的排序规则在数据库级别解决。这很重要,因为您可能希望在sort列上有一个索引以获得最佳性能。

但是,还有其他一些用例,它们可以将过滤与其他排序组合在一起,而不是纯列值,例如根据描述的长度,列的总和或平均值等。因此,我包括一个JPA解决方案:

最近我为此感到挣扎,但恐怕Pageable界面不支持此功能。

解决方案是使用EntityManagerCriteriaBuilderCriteriaQuerySpecification并手动实现分页。您可以找到解决方案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使用LIMITOFFSET

选择页面
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() + "%")
    );
}