• JPA 分页


    1. 概述

    本文说明了如何在Java 持久性 API 中实现分页

    它解释了如何使用基本 JQL 和更安全、基于标准的 API 进行分页,讨论了每个实现的优点和已知问题。

    2. 使用 JQL 和setFirstResult(),setMaxResults()API 进行分页

    实现分页的最简单方法是使用Java 查询语言 – 创建一个查询并通过setMaxResultss etFirstResult 对其进行配置:

    1. Query query = entityManager.createQuery("From Foo");
    2. int pageNumber = 1;
    3. int pageSize = 10;
    4. query.setFirstResult((pageNumber-1) * pageSize);
    5. query.setMaxResults(pageSize);
    6. List <Foo> fooList = query.getResultList();
    Copy

    API 很简单:

    • setFirstResult(int):设置结果集中的偏移位置以开始分页
    • setMaxResults(int):设置页面中应包含的最大实体数

    2.1. 总数和最后一页

    对于更完整的分页解决方案,我们还需要获取总结果计数

    1. Query queryTotal = entityManager.createQuery
    2. ("Select count(f.id) from Foo f");
    3. long countResult = (long)queryTotal.getSingleResult();
    Copy

    计算最后一页也非常有用:

    1. int pageSize = 10;
    2. int pageNumber = (int) ((countResult / pageSize) + 1);
    Copy

    请注意,这种获取结果集总数的方法确实需要额外的查询(针对计数)。

    3. 使用实体的 ID 使用 JQL 进行分页

    一个简单的替代分页策略是首先检索完整的 ID,然后根据这些 ID 检索完整的实体。这样可以更好地控制实体获取 - 但这也意味着它需要加载整个表才能检索 id:

    1. Query queryForIds = entityManager.createQuery(
    2. "Select f.id from Foo f order by f.lastName");
    3. List<Integer> fooIds = queryForIds.getResultList();
    4. Query query = entityManager.createQuery(
    5. "Select f from Foo e where f.id in :ids");
    6. query.setParameter("ids", fooIds.subList(0,10));
    7. List<Foo> fooList = query.getResultList();
    Copy

    最后,还要注意,它需要 2 个不同的查询来检索完整结果。

    4. 使用标准 API 使用 JPA 进行分页

    接下来,让我们看看如何利用 JPA 标准 API来实现分页:

    1. int pageSize = 10;
    2. CriteriaBuilder criteriaBuilder = entityManager
    3. .getCriteriaBuilder();
    4. CriteriaQuery<Foo> criteriaQuery = criteriaBuilder
    5. .createQuery(Foo.class);
    6. Root<Foo> from = criteriaQuery.from(Foo.class);
    7. CriteriaQuery<Foo> select = criteriaQuery.select(from);
    8. TypedQuery<Foo> typedQuery = entityManager.createQuery(select);
    9. typedQuery.setFirstResult(0);
    10. typedQuery.setMaxResults(pageSize);
    11. List<Foo> fooList = typedQuery.getResultList();
    Copy

    当目标是创建动态、故障安全查询时,这很有用。与“硬编码”、“基于字符串”的 JQL 或 HQL 查询相比,JPA 条件减少了运行时失败,因为编译器会动态检查查询错误。

    使用 JPA 标准以非常简单的方式获取实体总数

    1. CriteriaQuery<Long> countQuery = criteriaBuilder
    2. .createQuery(Long.class);
    3. countQuery.select(criteriaBuilder.count(
    4. countQuery.from(Foo.class)));
    5. Long count = entityManager.createQuery(countQuery)
    6. .getSingleResult();
    Copy

    最终结果是使用 JPA 标准 API 的完整分页解决方案

    1. int pageNumber = 1;
    2. int pageSize = 10;
    3. CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
    4. CriteriaQuery<Long> countQuery = criteriaBuilder
    5. .createQuery(Long.class);
    6. countQuery.select(criteriaBuilder
    7. .count(countQuery.from(Foo.class)));
    8. Long count = entityManager.createQuery(countQuery)
    9. .getSingleResult();
    10. CriteriaQuery<Foo> criteriaQuery = criteriaBuilder
    11. .createQuery(Foo.class);
    12. Root<Foo> from = criteriaQuery.from(Foo.class);
    13. CriteriaQuery<Foo> select = criteriaQuery.select(from);
    14. TypedQuery<Foo> typedQuery = entityManager.createQuery(select);
    15. while (pageNumber < count.intValue()) {
    16. typedQuery.setFirstResult(pageNumber - 1);
    17. typedQuery.setMaxResults(pageSize);
    18. System.out.println("Current page: " + typedQuery.getResultList());
    19. pageNumber += pageSize;
    20. }
    Copy

    5. 结论

    本文探讨了 JPA 中提供的基本分页选项。

    有些缺点 - 主要与查询性能有关,但这些缺点通常被改进的控制和整体灵活性所抵消。

    正在上传…重新上传取消

    这个Spring JPA教程的实现可以在GitHub项目中找到 - 这是一个基于Maven的项目,所以它应该很容易导入和运行。

  • 相关阅读:
    GaussDB(DWS)云原生数仓技术解析:湖仓一体,体验与大数据互联互通
    LeetCode 每日一题 2022/11/21-2022/11/27
    LeetCode【46】全排列
    Nginx的X-Accel-Redirect实现大文件下载
    进程调度的基本关系
    【HCIE】01.IGP高级特性
    PySpark之Python版本如何选择(详细版)
    Element UI + Vue 新增和编辑共用表单校验无法清除问题(已解决)
    java项目整合linux上的redis
    react中hook 函数的使用
  • 原文地址:https://blog.csdn.net/allway2/article/details/128095020