Spring Data JPA之分页查询

一、普通:分页+排序

因为PagingAndSortingRepository,我们总是可以传入Sort和Pageable对查询结果进行排序和分页(derived query、example查询和@Query查询都支持)。

// 当查询方法中有多个参数的时候,Pageable/Sort建议做为最后一个参数传入

@Query("select u from User u")
Page<User> findALL(Pageable pageable);

Page<User> findByNickName(String nickName, Pageable pageable);

// 可以返回Page<T>对象,也可以返回List<T>对象

由于JPA(JPQL)不支持Limit,请采用其他方法实现limit需求,https://stackoverflow.com/questions/44565820/what-is-the-limit-clause-alternative-in-jpql 

二、单表:分页 + 排序 + 动态查询

  1. repository继承JpaSpecificationExecutor<T>接口;
    • 最终调用Page<T> findAll(@Nullable Specification<T> spec, Pageable pageable)实现“分页+排序”功能
  2. 构造Specification<T> spec;
    • 搜索Specification能得到很多网页结果
      interface Specification<T> {
          Predicate toPredicate(Root<T> root, CriteriaQuery query, CriteriaBuilder cb);
      }
  3. 构造Pageable pageable,
    • Pageable是可以带Sort的
      Pageable sortedByName = 
        PageRequest.of(0, 3, Sort.by("name"));
       
      Pageable sortedByPriceDesc = 
        PageRequest.of(0, 3, Sort.by("price").descending());
       
      Pageable sortedByPriceDescNameAsc = 
        PageRequest.of(0, 5, Sort.by("price").descending().and(Sort.by("name")));
  4. 等待补充

三、多表:分页 + 排序 + 动态查询

  1. 选择主表
    • 一般选择带“排序字段”的表作为主表,最终的目的是“分页+排序”只存在于主表
    • 主辅表都可以有“动态查询”
  2. 先操作辅表
    • 对辅表进行动态查询等操作,获取逻辑外键的Set集合;
    • 把辅表查询得到的逻辑外键的Set集合,返回给主表;
  3. 再操作主表
    • 把辅表返回的逻辑外键的Set集合当做一个查询条件
      Predicate predicate = root.get("ip").as(String.class).in(ipCollect);
  4. 完成分页和排序操作
    • 还是利用Page<T> findAll(@Nullable Specification<T> spec, Pageable pageable)完成“分页+排序”操作
  5. 填充辅表字段
    • 对分页结果进行Stream操作,补上辅表的字段信息
    • 最终的pagesize数量不会很大,补充字段的操作性能消耗不会很大;
    • Page<T>的返回结果可以通过在entity中补充@Transient字段,后续进行填充

三、相关问题:

  1. 最后生成的SQL是什么样子的?
    • 是SQL子查询
  2. 多个表都有排序字段的情况下,怎么确定主表?
    • 根据传入的排序字段名,决定哪张为主表,这种情况发生时,大概率是表结构的设计有问题
  3. 这么做的意义是什么?
    • “面向DB编程” VS “面向对象编程”
    • 业务逻辑尽可能放在代码里实现,而不是SQL中
    • 在互联网开发背景下,更倾向于把DB当中带事务支持的容器,把DB的性能压力解耦到应用层
    • 少手写JPQL/SQL,少用JOIN,可以在数据库字段频繁变更,需求频繁变化的情况下,提高开发效率
  4. 这个方案有什么不好的地方吗?
    • JPA在没有物理外键的情况下,无法构建级联关系,这个方法确实可用,但不优雅
  5. 待补充
原文地址:https://www.cnblogs.com/echo1937/p/13151837.html