【问题标题】:How add pagination on Criteria api using typedQuery?如何使用 typedQuery 在 Criteria api 上添加分页?
【发布时间】:2019-05-10 11:55:37
【问题描述】:

我正在使用具有可分页功能的 Criteria API 返回具有可分页功能的 Page<MyClass>,但是当我插入 setFirstResultsetMaxResults 时,查询始终返回 10 个元素。

如果我从 TypedQuery 中删除 setFirstResultsetMaxResults,我的 typedQuery.getResultList() 会返回所有元素,但显然没有分页。

我有一个服务调用我的标准发送我的主要功能的分页peopleRepository.filter

public Page<People> filtrarParcial(String name, String rg, String mom, String cpf, String nickname, Integer pageNumber, Integer pageSize, List<String> sort) {
    List<Sort.Order> orders = new ArrayList<>();

    PageRequest pageRequest = PageRequest.of(pageNumber, pageSize, Sort.by(orders));

    Page<People> listPeople = peopleRepository.filter(name, rg, mom, cpf, nickname, pageRequest);

    return listPeople;
}

我的存储库实现

@Service
public class PeopleRepositoryImpl implements PeopleRepositoryQueries {
    @PersistenceContext
    private EntityManager manager;

    @Transactional(readOnly = true)
    public Page<People> filter(String name, String rg, String mom, String cpf, String nickname, Pageable pageable) {

        CriteriaBuilder criteriaBuilder = manager.getCriteriaBuilder();
        CriteriaQuery<People> query = criteriaBuilder.createQuery(People.class);

        Root<People> root = query.from(People.class);

        Path<String> nomePath = root.<String>get("name");

        List<Predicate> predicates = new ArrayList<Predicate>();

        if(!nome.equals("")) {
            Predicate nomeIgual = criteriaBuilder.like(nomePath, "%" +name.toUpperCase() + "%");
            predicates.add(nomeIgual);
        }

        query.where((Predicate[]) predicates.toArray(new Predicate[0]));

        int paginaAtual = pageable.getPageNumber();
        int totalRegistrosPorPagina = pageable.getPageSize();
        int primeiroRegistro = paginaAtual * totalRegistrosPorPagina;

        TypedQuery<People> typedQuery = manager.createQuery(query);

//      typedQuery.setFirstResult(primeiroRegistro);
//      typedQuery.setMaxResults(totalRegistrosPorPagina);

        Integer totalRows = typedQuery.getResultList().size();

        Long total = totalRows.longValue();
        return new PageImpl<>(typedQuery.getResultList(), pageable, total);
    }

如果我搜索名称为 ma​​rcos 的人,typedQuery.getResultList() 仅返回 10 个元素,同时按页面显示相同数量的元素(在我的数据库中有 180 个)。如果我删除它

typedQuery.setFirstResult(primeiroRegistro);
typedQuery.setMaxResults(totalRegistrosPorPagina);

然后typedQuery.getResultList()返回180个元素但有分页,所有180个元素都在一个页面内没有分页

【问题讨论】:

  • 如果您设置 FirstResult 和 MaxResults 查询应返回最大 MaxResults 元素(在您的情况下为 10)。第 0 页 -> 元素 0 - 9,第 1 页 -> 元素 10 - 19 ... 第 17 页 -> 元素 170 -> 179。FirstResult 是偏移量 (0, 10 ... 170),MaxResults 是最大数量每页元素。
  • 是的,按页面显示最大元素,但仅显示此内容。我在数据库中有 120 个元素,并且在没有其他页面的情况下仅返回 json 中的 10 个元素(totalelements),如果我尝试访问 ?page=1 不存在。

标签: java spring spring-boot criteria-api


【解决方案1】:

尝试以下配置。

CriteriaQuery<Long> countQuery = criteriaBuilder.createQuery(Long.class);
Root<People> entity_ = countQuery.from(query.getResultType());
entity_.alias("entitySub"); //use the same alias in order to match the restrictions part and the selection part
countQuery.select(criteriaBuilder.count(entity_));
Predicate restriction = query.getRestriction();
if (restriction != null) {
    countQuery.where(restriction); // Copy restrictions
}
Long totalCount=entityManager.createQuery(countQuery).getSingleResult();


query.setFirstResult(pageable.getOffset());
query.setMaxResults(pageable.getPageSize());
List<People> result = query.getResultList();
return PageableExecutionUtils.getPage(result,pageable, () -> totalCount);

【讨论】:

  • 不确定是否是在原始答案时,但 PageableExecutionUtils 现在已弃用。据我所知,这将从数据库中提取每个结果以计算计数,而不是执行count(*) 类型查询。
猜你喜欢
  • 2019-05-31
  • 2019-04-03
  • 1970-01-01
  • 1970-01-01
  • 2021-12-22
  • 2011-07-17
  • 2011-08-19
  • 1970-01-01
  • 2021-05-28
相关资源
最近更新 更多