Spring JPA find分页示例详解

作者:烟雨戏江南 时间:2023-05-09 00:36:46 

前言

在现实项目中,数据量一般都不小,如果一次性全部请求出来,肯定是影响性能,而且大量数据展示到页面上观感也不好。这时我们就需要用到分页,给定一个 pageSize,每次请求的数量就是 pageSize 的大小,这样既可以节约时间,又可以美化页面。Spring JPA 就为我们提供这样一个方法,准确来说是提供了一个对象用来约束数据按照分页的形式进行请求。

源码

findAll(Pageable pageable):从入参 pageable 我们可以猜到,就是这个对象来帮助我们对数据进行分页查询。那我们如何创建 pageable 对象呢?如何用他去实现分页呢?先看一下源码:

/**
* Creates a new {@link Pageable} for the first page (page number {@code 0}) given {@code pageSize} .
*
* @param pageSize the size of the page to be returned, must be greater than 0.
* @return a new {@link Pageable}.
* @since 2.5
*/
static Pageable ofSize(int pageSize) {
  return PageRequest.of(0, pageSize);
}

由此可见,pageable 对象需要 pageRequest.of 去创建,那我们再看看 pageRequest.of 的源码:

/**
* Creates a new unsorted {@link PageRequest}.
*
* @param page zero-based page index, must not be negative.
* @param size the size of the page to be returned, must be greater than 0.
* @since 2.0
*/
public static PageRequest of(int page, int size) {
  return of(page, size, Sort.unsorted());
}
/**
* Creates a new {@link PageRequest} with sort parameters applied.
*
* @param page zero-based page index.
* @param size the size of the page to be returned.
* @param sort must not be {@literal null}, use {@link Sort#unsorted()} instead.
* @since 2.0
*/
public static PageRequest of(int page, int size, Sort sort) {
  return new PageRequest(page, size, sort);
}
/**
* Creates a new {@link PageRequest} with sort direction and properties applied.
*
* @param page zero-based page index, must not be negative.
* @param size the size of the page to be returned, must be greater than 0.
* @param direction must not be {@literal null}.
* @param properties must not be {@literal null}.
* @since 2.0
*/
public static PageRequest of(int page, int size, Direction direction, String... properties) {
  return of(page, size, Sort.by(direction, properties));
}

从源码可以看出,pageRequest.of 需要传入 page(第几页)和 size(页面大小),另外如果需要排序的话,还需要传入 sort(这个对象前一篇已经分析过了)。

一、单纯分页查询

所谓的单纯分页查询,就是只分页,不做其他的动作,这样一来,我们只需要传入 pagepageSize 即可。
control 层

@GetMapping("findAllPage")
public Page<User> findAllPage(int page, int pageSize) {
   Pageable pageable = PageRequest.of(page, pageSize);
   return userService.findAllPage(pageable);
}

执行请求findAllPage?page=0&pageSize=5(第一页、页面大小为5),控制台打印如下:

Hibernate: select user0\_.id as id1\_0\_, user0\_.age as age2\_0\_, user0\_.name as name3\_0\_ from user user0\_ limit ?
Hibernate: select count(user0\_.id) as col\_0\_0\_ from user user0\_

查询结果

{
   "content": [{
                   "id": 20,
                   "name": "aa",
                   "age": 11
           }, {
                   "id": 21,
                   "name": "bb",
                   "age": 12
           }, {
                   "id": 22,
                   "name": "cc",
                   "age": 11
           }, {
                   "id": 23,
                   "name": "dd",
                   "age": 16
           }, {
                   "id": 24,
                   "name": "ee",
                   "age": 17
           }
   ],
   "pageable": {
           "sort": {
                   "empty": true,
                   "sorted": false,
                   "unsorted": true
           },
           "offset": 0,
           "pageSize": 5,
           "pageNumber": 0,
           "unpaged": false,
           "paged": true
   },
   "last": false,
   "totalPages": 2,
   "totalElements": 6,
   "number": 0,
   "size": 5,
   "sort": {
           "empty": true,
           "sorted": false,
           "unsorted": true
   },
   "numberOfElements": 5,
   "first": true,
   "empty": false
}

结论

从上面的结果输出和控制台输出来看,它除了做了 limit 分页查询外,还做了求出了总数totalElements,还输出了总页数 totalPages。这些参数在我们实际项目中有的时候还是很有用的。

二、排序分页查询

所谓的排序分页,就是将数据先按照我们所需的方式进行排序,然后再进行分页查询
control 层

@GetMapping("findAllPageSort")
public Page<User> findAllPageSort(int page, int pageSize, String[] sorts, String[] paras) {
   List<Sort.Order> listOrder = new ArrayList<>();
   for(int i=0; i<sorts.length; i++){
       listOrder.add(new Sort.Order(sorts[i].toLowerCase().equals("asc") ?
               Sort.Direction.ASC : Sort.Direction.DESC, paras[i]));
   }
   Pageable pageable = PageRequest.of(page, pageSize, Sort.by(listOrder));
   return userService.findAllPage(pageable);
}

执行请求findAllPageSort?page=0&pageSize=5&sorts=asc,desc&paras=age,name(第一页,页面大小为5,先按照age升序,再按照name降序),控制台打印如下:

Hibernate: select user0_.id as id1_0_, user0_.age as age2_0_, user0_.name as name3_0_ from user user0_ order by user0_.age asc, user0_.name desc limit ?
Hibernate: select count(user0_.id) as col_0_0_ from user user0_

查询结果

{
"content": [{
"id": 26,
"name": "gg",
"age": 7
}, {
"id": 22,
"name": "cc",
"age": 11
}, {
"id": 20,
"name": "aa",
"age": 11
}, {
"id": 21,
"name": "bb",
"age": 12
}, {
"id": 23,
"name": "dd",
"age": 16
}
],
"pageable": {
"sort": {
"empty": false,
"sorted": true,
"unsorted": false
},
"offset": 0,
"pageNumber": 0,
"pageSize": 5,
"paged": true,
"unpaged": false
},
"totalElements": 7,
"last": false,
"totalPages": 2,
"number": 0,
"size": 5,
"sort": {
"empty": false,
"sorted": true,
"unsorted": false
},
"numberOfElements": 5,
"first": true,
"empty": false
}

三、方法整理

以下是整理的 pageable 对象可用的一些比较实用的方法

方法说明
boolean unpagedtrue:未进行分页,false:进行了分页
boolean isPagedtrue:进行了分页,false:未进行分页
int getPageNumber获取当前页数
int getPageSize获取页面大小
long getOffSet获取页面偏移量,相当于sql中的start
Sort getSort获取当前的排序规则
Pageable next获取下一页的分页信息(翻页中的下一页)
boolean hasPrevious是否有上一页
Pageable previous获取上一页的分页信息(翻页钟的上一页)
Pageable first获取首页分页信息
Pageable previousOrFirst如果没有上一页则回到首页

总结:

分页查询是实际项目中非常常见的需求,总体上看也没有什么比较难的地方,需要注意的就是排序了。到目前为止学习的都是JpaRepository自带的一些接口,下面我们就开始接触非自带的需要我们自己去构造的方法了。

来源:https://juejin.cn/post/7223586612927676476

标签:Spring,JPA,find,分页
0
投稿

猜你喜欢

  • Spring Boot配置接口WebMvcConfigurer的实现

    2023-11-27 23:28:50
  • 详解Android 中的文件存储

    2023-12-21 17:44:44
  • Java与Scala创建List与Map的实现方式

    2021-07-19 23:53:07
  • 浅析JAVA中过滤器、监听器、拦截器的区别

    2023-10-18 17:47:24
  • Android自定义控件(实现视图树绘制指示器)

    2023-11-14 17:11:59
  • Spring Boot示例分析讲解自动化装配机制核心注解

    2022-07-26 15:56:14
  • Flutter实现微信朋友圈功能

    2022-10-02 00:28:15
  • Springboot整合Dozer实现深度复制的方法

    2023-11-12 17:18:11
  • Android评分控件RatingBar使用实例解析

    2022-02-07 14:17:03
  • C#中闭包概念讲解

    2022-08-16 05:16:28
  • C#利用性能计数器监控网络状态

    2022-01-05 00:13:53
  • Java-String类最全汇总(下篇)

    2023-11-09 14:45:26
  • IDEA的默认快捷键设置与Eclipse的常用快捷键的设置方法

    2023-04-09 18:32:40
  • Unity UI或3D场景实现跟随手机陀螺仪的晃动效果

    2021-12-09 01:09:32
  • Maven将代码及依赖打成一个Jar包的方式详解(最新推荐)

    2022-03-31 06:52:47
  • java实现微信公众号发送模版消息

    2022-04-23 08:09:11
  • SpringCloud实现Redis在各个微服务的Session共享问题

    2022-07-14 06:33:19
  • C#浅拷贝和深拷贝实例解析

    2022-09-03 02:31:05
  • android自定义进度条渐变色View的实例代码

    2023-07-01 20:58:57
  • android 触屏的震动响应接口调用方法

    2021-08-04 08:33:34
  • asp之家 软件编程 m.aspxhome.com