java中实现分页的几种常见方式总结

作者:搏·梦 时间:2021-12-24 13:32:49 

1. 前言

无论是自我学习中,还是在工作中,固然会遇到与前端搭配实现分页的功能,发现有几种方式,特此记录一下。

2. 先说结论

  1. 分页功能直接交给前端实现(根据业务场景且仅仅只能用于数据量少的情况)。即后端不做任何数据的限制,直接把全部数据返回给前端,前端通过组件实现分页,筛选等功能。请不要轻视该方式,好处即只需要前后端交互一次。

  2. 使用数据库SQL的限制条件,即给搜索语句加上条件,限制查询出来的数据个数:

    1. mysql数据库是使用 limit n,m 从第n个开始,往后取m个(注 不包括第n个数据)

    2. oracle数据库是使用 OFFSET n ROWS FETCH NEXT m ROWS ONLY 从第n行开始,往后取m行(注 不包括第n行数据)

    3. oracle的可以查看这篇文章:oracle中将数据进行排序之后,获取前几行数据的写法(rownum、fetch方式)

  3. 使用List集合的截取功能实现,即将数据都查到内存中List集合,在内存中找到要的数据。当然有人说这种方式还不如第二点,但请具体情况具体分析,有可能需求要的数据,是从数据库中查询不到的,需要将原始数据查到内存加工处理数据之后得到,才能进行分页处理。(同理,该方法,只能根据需求且数据量少的情况)

  4. 使用优秀的插件PageHelper,真的很不错。

3. 例子

1. 数据库SQL的限制条件(limit、fetch)

先说结论

mysql写法:
SELECT * FROM user2
LIMIT (#{pageNum} - 1) * #{pageSize}, #{pageSize}

oracle写法:
SELECT * FROM user2
OFFSET (#{pageNum} - 1) * #{pageSize} ROWS FETCH NEXT #{pageSize} ROWS ONLY

直接看代码:

@Mapper
public interface PageTestDao {

// 查数据
// start:从第几条开始,向后要数据
// pageSize:一页多少条数据
   List<UserEntity> getUserInfoByParams(@Param("nameParam") String name,
                                        @Param("start") int start,
                                        @Param("pageSize") int pageSize);
// 返回总条数
   int getCountByParams(@Param("nameParam") String name);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.csdn2.page_test.dao.PageTestDao">

<sql id="nameCondition">
       <where>
           <if test="nameParam != null and nameParam != ''">
               name like CONCAT('%', #{nameParam}, '%')
           </if>
       </where>
   </sql>

<select id="getUserInfoByParams" resultType="com.example.csdn2.page_test.entity.UserEntity">
       SELECT * FROM user2
       <include refid="nameCondition" />
       LIMIT #{start}, #{pageSize}
   </select>

<select id="getCountByParams" resultType="int">
       SELECT COUNT(*) FROM user2
       <include refid="nameCondition" />
   </select>
</mapper>
@Service
@RequiredArgsConstructor
public class PageTestService {

private final PageTestDao pageTestDao;

public PageResponse<UserEntity> getPageTest(UserRequest userRequest) {
       final List<UserEntity> userEntityList = pageTestDao.getUserInfoByParams(userRequest.getNameParam(),
               userRequest.getStart(), userRequest.getPageSize());

final int total = pageTestDao.getCountByParams(userRequest.getNameParam());

return new PageResponse<>(userEntityList, total);
   }
}
// 若分页的需求很多,可把分页相关的参数抽出来
@Data
public class PageRequest {

// 第几页
   private int pageNum;

// 每页几行数据
   private int pageSize;

// 计算从第几行开始
// 无论是limit、还是fetch 都是从某一行数据开始,向后取 pageSize 条数据
   public int getStart() {
       if (pageNum <= 0) {
           return 0;
       }
       return (pageNum - 1) * pageSize;
   }
}

// 入参
@EqualsAndHashCode(callSuper = true)
@Data
public class UserRequest extends PageRequest {

// 搜索参数
   private String nameParam;
}

// 返回实体类,因为分页需要返回总条数,前端好做下标第几页
@Data
@AllArgsConstructor
public class PageResponse<T> {

private List<T> data;

// 总条数
   private int total;
}

@RestController
@RequiredArgsConstructor
public class PageTestController {

private final PageTestService pageTestService;

@PostMapping("/page-test")
   public PageResponse<UserEntity> getPageTest(@RequestBody UserRequest userRequest){
      return pageTestService.getPageTest(userRequest);
   }
}

java中实现分页的几种常见方式总结

2. 使用List集合的截取功能实现

1.先看一下List的截取

// 从第几个下标,到第几个下标
List<E> subList(int fromIndex, int toIndex);
public void test_ListSub() {
   // 创建模拟数据,字符串 0-9的集合
       final List<String> list = IntStream.range(0, 10)
               .mapToObj(i -> i + "")
               .collect(Collectors.toList());
       System.out.println(list);
       // 截取从下标0到5的数据
       System.out.println(list.subList(0, 5));
       // 截取从下标3到5的数据
       System.out.println(list.subList(3, 5));
   }

java中实现分页的几种常见方式总结

2.回归上述分页例子,代码改成如下:

dao层 不加 limit 条件

SELECT * FROM user2
 name like CONCAT('%', #{nameParam}, '%')

server层:

public PageResponse<UserEntity> getPageTestByListSub(UserRequest userRequest) {
       final List<UserEntity> allData = pageTestDao.getUserInfoByParamsNoLimit(userRequest.getNameParam());
       // 下标开始
       final int start = userRequest.getStart();
       // 下标结束
       final int end = start + userRequest.getPageSize();
       // 截取数据
       final List<UserEntity> userEntityList = allData.subList(start, end);

final int total = pageTestDao.getCountByParams(userRequest.getNameParam());
       return new PageResponse<>(userEntityList, total);
   }

3. 插件PageHelper

1.其实PageHelper官网中有详细的文档以及例子:https://pagehelper.github.io/docs/howtouse/

2.下面例子只是讲其与springboot结合的核心内容,即快速开发

3.引入相关jar包坐标到pom.xml中

<dependency>
       <groupId>com.github.pagehelper</groupId>
       <artifactId>pagehelper-spring-boot-starter</artifactId>
       <version>1.3.0</version>
</dependency>

4.dao层的sql不需要加 Limit 条件(因为PageHelper会自动帮忙加的)

SELECT * FROM user2
 name like CONCAT('%', #{nameParam}, '%')

5.service层修改如下:

public PageInfo<UserEntity> getPageTest(UserRequest userRequest) {
       // 告诉PageHelper数据要从第几页,每页多少条数据
       // 注:一定要在select查询语句之前使用该方法,否则无效
       PageHelper.startPage(userRequest.getPageNum(), userRequest.getPageSize());

// 查询sql
       final List<UserEntity> userEntityList = pageTestDao.getUserInfoByParamsNotLimit(userRequest.getNameParam());

// 返回dto,使用插件自带的PageInfo
       return new PageInfo<>(userEntityList);

// 上述逻辑还可以简写为:
// return PageHelper.startPage(userRequest.getPageNum(), userRequest.getPageSize())
           // .doSelectPageInfo(() -> pageTestDao.getUserInfoByParamsNotLimit(userRequest.getNameParam()));
   }

6.结果如下(与之前查询结果一致,没问题):

{
    "total": 9,
    "list": [
        {
            "name": "4a",
            "pwd": "D"
        },
        {
            "name": "5a",
            "pwd": "E"
        },
        {
            "name": "6a",
            "pwd": "F"
        }
    ],
    "pageNum": 2,
    "pageSize": 3,
    "size": 3,
    "startRow": 4,
    "endRow": 6,
    "pages": 3,
    "prePage": 1,
    "nextPage": 3,
    "isFirstPage": false,
    "isLastPage": false,
    "hasPreviousPage": true,
    "hasNextPage": true,
    "navigatePages": 8,
    "navigatepageNums": [
        1,
        2,
        3
    ],
    "navigateFirstPage": 1,
    "navigateLastPage": 3
}

7.为什么说该插件很优秀呢查看PageInfo的返回参数,核心内容:

// 当前页
   private int pageNum;
   // 每页的数量
   private int pageSize;
   // 当前页的数量
   private int size;

// 总记录数
   private long total;
   // 总页数
   private int pages;
   // 结果集
   private List<T> list;

// 以下内容都是其自动帮生成的
// 对于前端来说极其友好,前端分页功能的全部参数都包含了
   // 前一页的页码
   private int prePage;
   // 下一页的页码
   private int nextPage;
   // 是否为第一页
   private boolean isFirstPage = false;
   // 是否为最后一页
   private boolean isLastPage = false;
   // 是否有前一页
   private boolean hasPreviousPage = false;
   // 是否有下一页
   private boolean hasNextPage = false;
   // 导航条上的第一页的页码
   private int navigateFirstPage;
   // 导航条上的第一页的页码
   private int navigateLastPage;

8.查看PageHelper执行了什么sql语句

java中实现分页的几种常见方式总结

总结 

来源:https://blog.csdn.net/xueyijin/article/details/128365377

标签:java,分页
0
投稿

猜你喜欢

  • SpringBoot2.0集成WebSocket实现后台向前端推送信息

    2023-08-22 18:50:39
  • java使用Cookie判断用户登录情况的方法

    2021-11-28 15:12:40
  • 浅试仿 mapstruct实现微服务编排框架详解

    2022-07-12 13:20:44
  • Spring@Value使用获取配置信息为null的操作

    2021-08-01 23:46:27
  • C# 获取某个时间的0点0分和23点59分59秒

    2023-03-02 10:05:18
  • Java实现定时任务的方法详解

    2022-12-30 04:14:00
  • 关于SpringSecurity配置403权限访问页面的完整代码

    2023-11-13 02:03:59
  • Android实战教程第五篇之一键锁屏应用

    2023-12-03 18:47:36
  • Java之 TreeSet的详细使用说明

    2021-08-22 14:52:22
  • C#读写INI文件的方法

    2023-12-08 15:31:10
  • Eclipse的Debug调试技巧大全(总结)

    2023-11-25 06:14:06
  • 使用idea+gradle编译spring5.x.x源码分析

    2022-05-13 15:13:31
  • java实现word文档转pdf并添加水印的方法详解

    2023-05-26 02:59:18
  • 为spring get请求添加自定义的参数处理操作(如下划线转驼峰)

    2021-12-04 13:01:43
  • Java注解方式之防止重复请求

    2023-05-29 16:30:51
  • Android7.0 工具类:DiffUtil详解

    2023-02-24 01:43:46
  • c# 颜色选择控件的实现代码

    2022-04-27 07:22:58
  • android 多点触摸图片缩放的具体实现方法

    2023-03-14 05:49:31
  • springMvc注解之@ResponseBody和@RequestBody详解

    2022-10-09 17:57:19
  • JAVA IDEA 打开assert 设置方式

    2022-08-19 13:48:49
  • asp之家 软件编程 m.aspxhome.com