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

这篇具有很好参考价值的文章主要介绍了java中实现分页的常见几种方式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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 user2
    LIMIT (#{pageNum} - 1) * #{pageSize}, #{pageSize}
    
    oracle写法:
    SELECT * FROM user2
    OFFSET (#{pageNum} - 1) * #{pageSize} ROWS FETCH NEXT #{pageSize} ROWS ONLY
    
  2. 直接看代码:

    @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://www.toymoban.com/news/detail-409157.html

到了这里,关于java中实现分页的常见几种方式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • SpringBoot实现分页的三种方式

    一 自己封装Page对象实现 博客链接 二 使用sql实现分页 2.1 场景分析 前段传递给给后台什么参数? 当前页码 currentPage 每页显示条数 pageSize 后台给前端返回什么数据? 当前页数据 List 总记录数 totalCount 2.2 前段代码 2.3 后端代码 PageBean mapper service impl controller 三 使用PageHelper插件

    2024年02月10日
    浏览(51)
  • java实现调用http请求的几种常见方式

    ------ Oracle中文开发者社区 ------ 如果你想要学习编程,关注本博客,持续获得技术支持,持续获得技术咨询 java开发·企业官方账号 Oracle中国官方账号 Java中国管理部 全网粉丝30万+ 华为云享专家 阿里专家博主 CSDN内容合伙人 CSDN原力计划作者 51CTO专家博主 CSDN博客V账号 毕业于四川

    2024年02月04日
    浏览(56)
  • 【java缓存、redis缓存、guava缓存】java中实现缓存的几种方式

    这种方式可以简单实现本地缓存,但是实际开发中不推荐使用,下面我们来实现一下这种方式。 首先创建一个管理缓存的类 这个类中有一个静态代码块,静态代码块会在类加载时就执行,我们可以在这里完成对缓存的初始化,决定缓存内一开始就有哪些数据 另外我们还可以

    2024年02月16日
    浏览(36)
  • Java求质数常见几种方式

    该方法的作用是判断一个整数是否是质数(即只能被1和自身整除的正整数)。方法接收一个整数参数num,返回一个布尔值,表示num是否为质数。 方法的实现原理是使用for循环从2到num的平方根(简单思考就可以想到不需要遍历到num-1)进行遍历,判断num是否能被这个数整除。

    2024年02月15日
    浏览(48)
  • Java中常见的几种HttpClient调用方式

    一、HttpURLConnection调用 方式一: 方式二: 缺点:不能直接使用池化技术,需要自行处理输入输出流 二、apache common封装HttpClient 引入依赖 实现 三、CloseableHttpClient 可以使用连接池保持连接,并且过期自动释放。引入jar包 引入依赖 实现 非连接池连接: 四、OkHttp3 引入依赖 实

    2024年02月04日
    浏览(56)
  • Java中String类的几种常见遍历方式

    今天小小的给自己总结一下String类的几种常见遍历方式,如下。 charAt(): charAt(int index) :返回 char指定索引处的值。 toCharArray() : toCharArray() :将此字符串转换为新的字符数组。 然后按照遍历字符串数组的方式遍历即可,可采用普通for循环遍历,也可以采用增强for循环遍历。 sub

    2024年02月16日
    浏览(45)
  • Java分页查询的几种实现方法

    最近在做需求的过程中遇到几个需要分页查询的需求,我也对分页有了较深的了解。分页一般分为两种一种是直接在sql中分页,一种是在内存中分页。本文仅针对内存中分页做记录。 第一种    如果是一个查询接口,向接口中传入page,和size(page默认值1,size默认值10)即可

    2024年02月06日
    浏览(88)
  • Linux 下通过 java 命令启动 jar 包的几种常见方式

    Linux 下通过 java 命令启动 jar 包的几种常见方式 一、后台启动jar包命令 方法一:直接启动 jar 包服务 方法二:后台启动 jar 包服务 方法三:后台不挂断启动 方式四:指定日志输出的启动 方式五:指定配置文件启动 方式六:指定配置文件,使用系统默认的log配置,不另行指定

    2024年02月13日
    浏览(43)
  • C# 读取Excel的几种常见方式及实现步骤

    目录 1.使用 Microsoft Office Interop Excel 库 2.使用 OLEDB 数据库连接方式 3. 使用 EPPlus 库 在 C# 中,我们可以使用以下几种方式将 Excel 文件中的数据读取到 DataTable 中: 1.使用 Microsoft Office Interop Excel 库 这种方法需要安装 Microsoft Office,并且性能较低。具体实现步骤如下: 2.使用 O

    2024年02月12日
    浏览(40)
  • Windows Bat实现延时功能的几种常见方式

    在 bat 批处理中实现延时功能的几种常用方式 使用ping命令可以实现延时的效果,命令如下: -n 指定 ping 的次数,每次大概间隔1s, nul 将 ping 过程回显信息给屏蔽 ping 命令实现的延时,时间精度:大约1s,内存占用: ping 命令所占用空间 注意闭坑:ping 从第1次发出请求到接收

    2024年02月11日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包