文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2023-08-31 20:54

关注

文章目录

1. 前言

  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)

  1. 先说结论

    mysql写法:SELECT * FROM user2LIMIT (#{pageNum} - 1) * #{pageSize}, #{pageSize}oracle写法:SELECT * FROM user2OFFSET (#{pageNum} - 1) * #{pageSize} ROWS FETCH NEXT #{pageSize} ROWS ONLY
  2. 直接看代码:

    @Mapperpublic 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);}
    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@RequiredArgsConstructorpublic 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);    }}
    // 若分页的需求很多,可把分页相关的参数抽出来@Datapublic 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)@Datapublic class UserRequest extends PageRequest {    // 搜索参数    private String nameParam;}// 返回实体类,因为分页需要返回总条数,前端好做下标第几页@Data@AllArgsConstructorpublic class PageResponse<T> {    private List<T> data;// 总条数    private int total;}
    @RestController@RequiredArgsConstructorpublic class PageTestController {    private final PageTestService pageTestService;    @PostMapping("/page-test")    public PageResponse<UserEntity> getPageTest(@RequestBody UserRequest userRequest){       return pageTestService.getPageTest(userRequest);    }}

    在这里插入图片描述

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));    }

    在这里插入图片描述

  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.pagehelpergroupId>        <artifactId>pagehelper-spring-boot-starterartifactId>        <version>1.3.0version>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语句
    在这里插入图片描述

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

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯