当前位置:   article > 正文

MyBatis 分页插件 PageHelper 使用说明_pagehelper offsetpage

pagehelper offsetpage

目录

PageHelper 分页插件概述

PageHelper 方式分页

Mapper 接口参数分页

ISelect 接口方式分页

PageInfo 分页对象信息


本文环境:Spring boot 2.3.5 + Java jdk 8 + Mysql + Log4j2  + MyBatis 3.5.7 + PageHelper 5.2.1

搭建 Spring boot + Mybatis 环境

PageHelper 分页插件概述

PageHelper 官网:MyBatis 分页插件 PageHelper
PageHelper GitHubGitHub - pagehelper/Mybatis-PageHelper: Mybatis通用分页插件
PageHelper 集成 Spring Boot:GitHub - pagehelper/pagehelper-spring-boot: pagehelper-spring-boot

1、PageHelper 分页插件支持任何复杂的单表、多表分页。

2、物理分页:支持常见的 12 种数据库:Oracle, MySql, MariaDB, SQLite, DB2, PostgreSQL, SqlServer 等。

3、多种分页方式支持常见的RowBounds(PageRowBounds),PageHelper.startPage 方法调用,Mapper 接口参数调用,QueryInterceptor 拦截器方式

4、Spring boot 项目推荐直接引用 pagehelper-spring-boot-starter 启动器:

  1. <!--mybatis 分页插件 pagehelper 内部依赖了 mybatis-spring-boot-starter 启动器 以及 com.github.pagehelper 插件 -->
  2. <!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper-spring-boot-starter -->
  3. <dependency>
  4. <groupId>com.github.pagehelper</groupId>
  5. <artifactId>pagehelper-spring-boot-starter</artifactId>
  6. <version>1.3.1</version>
  7. </dependency>

5、pagehelper-spring-boot-starter 启动器的自动配置类与配置属性如下,默认情况下,导入依赖后即可进行分页,如果需要自定义配置,则可以从 PageHelperProperties 中查看配置项:
    com.github.pagehelper.autoconfigure.PageHelperAutoConfiguration
    com.github.pagehelper.autoconfigure.PageHelperProperties

6、application.yml 全局配置文件中 mybatis 分页插件 pageHelper 常用配置:

  1. #mybatis 分页插件 pageHelper 配置
  2. pagehelper:
  3. #支持通过 Mapper 接口参数来传递分页参数,为 true 时,分页插件会从查询方法的参数值中查找 pageNum、pageSize 参数的值进行自动分页。默认值 false.
  4. supportMethodsArguments: true
  5. #分页合理化参数,为 true 时,pageNum<=0 会查询第一页, pageNum>pages(超过总数时),会查询最后一页。默认false 时,直接根据参数进行查询。
  6. reasonable: true
  7. #设置为 true 时,如果 pageSize=0 或者 RowBounds.limit = 0, 就会查询出全部的结果(相当于没有执行分页查询,但是返回结果仍然是 Page 类型),默认值为 false,
  8. pageSizeZero: true

PageHelper 方式分页

1、其实分页的关键是获取符合查询 sql 条件的总条数,只要有了它,再根据传入的参数 pageNum,pageSize 就能计算出任何想要的数据,比如总页数,上一页,下一页等等。

2、比如是在代码里面写 sql 时,则只需要在目标 sql 外面再包装一层,再查询一下 count(*) 即可获取到本 sql 的总条数,而 mybatis 的 sql 因为是在配置文件中或者在注解上,比较特殊,所以无法用常规手段获取。

3、一个 Controller 中总有几个查询的接口,让其实现分页非常简单,只需要在查询前开启分页:PageHelper.startPage,然后再返回结果后,包装 Page 对象 new PageInfo(List<T> list) 即可。

4、只有紧跟在 PageHelper.startPage、PageHelper.offsetPage 方法后的第一个 Mybatis 的查询(Select)方法会被分页,除非再次调用 PageHelper.startPage 或者调用 PageHelper.offsetPage。

  1. //控制层方法:http://localhost:8080/findByKeywordPage1?pageNum=2&pageSize=4
  2. @GetMapping("/findByKeywordPage1")
  3. public PageInfo findByKeywordPage1(String keyword, Integer pageNum, Integer pageSize) {
  4. pageNum = pageNum == null || pageNum <= 0 ? 0 : pageNum;
  5. pageSize = pageSize == null || pageSize <= 0L ? 0 : pageSize;
  6. /**
  7. * 1、PageHelper.startPage(int pageNum, int pageSize):开始分页,此时 XxxMapper 返回的集合是 {@link com.github.pagehelper.Page} 分页对象
  8. * total(总记录数) 等于 ((Page)list).getTotal();
  9. * 2、PageHelper.offsetPage:开始分页,底层与 startPage 是一样的.
  10. * 3、如果 pageNum 或者 pageSize 为 0,则不分页,默认查询所有,此时 XxxMapper 返回的集合不再是 {@link com.github.pagehelper.Page} 分页对象
  11. * 此时 size(当前页的数量)、total(总记录数) 都是等于普通的 list.size()
  12. * 4、只有紧跟在 PageHelper.startPage、PageHelper.offsetPage 方法后的第一个 Mybatis 的查询(Select)方法会被分页。
  13. */
  14. if (pageNum != 0 && pageSize != 0) {
  15. //PageHelper.startPage(pageNum, pageSize);
  16. PageHelper.offsetPage(pageNum, pageSize);
  17. }
  18. List<Dept> deptList = deptMapper.findByKeyword(keyword);
  19. /**
  20. * PageInfo(List<T> list):包装 Page 对象,默认导航页码为8
  21. * PageInfo(List<T> list, int navigatePages):包装 Page 对象,指定导航页码数量
  22. */
  23. PageInfo pageInfo = new PageInfo(deptList);
  24. return pageInfo;
  25. }
  1. //DeptMapper 接口:根据关键字模糊查询,默认查询所有
  2. List<Dept> findByKeyword(String keyword);
  1. <!-- DeptMapper.xml 映射 -->
  2. <!-- 根据关键字模糊查询,不为空时才拼 like 条件,否则默认查询所有.-->
  3. <select id="findByKeyword" resultType="com.wmx.hb.pojo.Dept" parameterType="string">
  4. select * from dept
  5. <where>
  6. <if test="keyword!=null">
  7. dname like concat('%',concat(#{keyword},'%')) or loc like concat('%',concat(#{keyword},'%'))
  8. </if>
  9. </where>
  10. order by deptno desc
  11. </select>

/hb/blob/master/src/main/java/com/wmx/hb/controller/DeptController.java
/hb/blob/master/src/main/java/com/wmx/hb/mapper/DeptMapper.java
/hb/blob/master/src/main/resources/myBatis/mapper/base/DeptMapper.xml 

Mapper 接口参数分页

1、只要 XxxMapper 接口的方法中含有参数 pageNum、pageSize,则会自动进行分页,不需要在  XxxMapper.xml 中进行任何处理。

2、此种方式时必须配置 pagehelper.supportMethodsArguments=true,开启支持 Mapper 方法参数分页.

  1. //控制层方法
  2. @PostMapping("/findByDept")
  3. public PageInfo<Dept> findByDept(@RequestBody(required = false) Dept dept, Integer pageNum, Integer pageSize) {
  4. pageNum = pageNum == null || pageNum <= 0L ? 1 : pageNum;
  5. pageSize = pageSize == null || pageSize <= 0L ? 2 : pageSize;
  6. //此时必须配置 pagehelper.supportMethodsArguments=true,开启支持 Mapper 方法参数分页.
  7. //pageNum、pageSize 也可以直接是 dept 对象的属性,当 pageNum!= null && pageSize!= null 时,也会自动分页.
  8. List<Dept> deptList = deptMapper.findByDept(dept, pageNum, pageSize);
  9. PageInfo<Dept> pageInfo = new PageInfo<Dept>(deptList);
  10. return pageInfo;
  11. }
  1. /**DeptMapper 接口方法
  2. * 1、查询指定部门的信息,将实体对象中不为空的属性都作为 where 条件,默认查所有。
  3. * 2、使用 org.apache.ibatis.annotations.Param 注解可以为 XxxMapper 接口方法指定多个参数。
  4. * 3、多个参数会被封装成一个 map,map 的 key 是使用 @Param 注解指定的值,value 是参数值。
  5. * 4、如果是级联对象,则 XxxMapper.xml 映射文件中也是级联取值,如 dept.deptno、dept.dname,前提是 dept 不能为 null,否则异常.
  6. * 5、pageNum、pageSize 也可以直接是 dept 对象的属性,当 pageNum!= null && pageSize!= null 时,也会自动分页.
  7. *
  8. * @param dept
  9. * @param pageNum :查询的页码,从1开始
  10. * @param pageSize :每页显示的条数
  11. * @return
  12. */
  13. List<Dept> findByDept(@Param("dept") Dept dept, @Param("pageNum") int pageNum, @Param("pageSize") int pageSize);
  1. <!--dept是对象,所以需要级联取值,必须不等于 null,才能级联取值-->
  2. <!--拼接 where 条件前进行参数是否为空判断。返回值类型指定为 List 中的元素类型-->
  3. <!--where 标签会自动删除内容开头的 and 或者 or 字符串 -->
  4. <select id="findByDept" resultType="com.wmx.hb.pojo.Dept">
  5. SELECT t1.deptno,t1.dname,t1.loc from dept t1
  6. <where>
  7. <if test="dept !=null and dept.deptno!=null">
  8. deptno = #{dept.deptno}
  9. </if>
  10. <if test="dept !=null and dept.dname!=null and dept.dname !=''">
  11. and dname like concat('%',concat(#{dept.dname},'%'))
  12. </if>
  13. <if test="dept !=null and dept.loc!=null and dept.loc!=''">
  14. and loc like concat('%',concat(#{dept.loc},'%'))
  15. </if>
  16. </where>
  17. </select>

ISelect 接口方式分页

1、写法和 PageHelper 方式差不多,如下所示:

  1. //控制层方法
  2. @GetMapping("/findByKeyword")
  3. public PageInfo<Dept> findByKeyword(String keyword, Integer pageNum, Integer pageSize) {
  4. pageNum = pageNum == null || pageNum <= 0 ? 0 : pageNum;
  5. pageSize = pageSize == null || pageSize <= 0L ? 0 : pageSize;
  6. //doSelectPage 返回的是 Page<E>对象,doSelectPageInfo 返回的是 PageInfo<E>对象.
  7. PageInfo<Dept> pageInfo = PageHelper.startPage(pageNum, pageSize).doSelectPageInfo(new ISelect() {
  8. @Override
  9. public void doSelect() {
  10. deptMapper.findByKeyword(keyword);
  11. }
  12. });
  13. return pageInfo;
  14. }
  1. // DeptMapper 接口方法:根据关键字模糊查询,默认查询所有
  2. List<Dept> findByKeyword(String keyword);
  1. <!-- DeptMapper.xml 映射文件:根据关键字模糊查询,不为空时才拼 like 条件,否则默认查询所有.-->
  2. <select id="findByKeyword" resultType="com.wmx.hb.pojo.Dept" parameterType="string">
  3. select * from dept
  4. <where>
  5. <if test="keyword!=null">
  6. dname like concat('%',concat(#{keyword},'%')) or loc like concat('%',concat(#{keyword},'%'))
  7. </if>
  8. </where>
  9. order by deptno desc
  10. </select>

PageInfo 分页对象信息

1、PageInfo 是对 Page<E> 结果的包装,包含了整个分页的详细信息,如下所示。

2、pagehelper 的 pageinfo(分页信息) 中的许多属性实际开发中可能用不到,通常也不会直接返回 pageinfo,而是会返回自己封装的数据对象,比如会有状态码,提示信息等等,此时可以在工具类中添加方法用于从 pageinfo 中提取需要的数据。

protected long total;    //总记录数

protected List<T> list;     //结果集

private int pageNum;  //当前页

private int pageSize;  //每页的数量
private int size;  //当前页的数量
//由于startRow和endRow不常用,这里说个具体的用法
//可以在页面中"显示startRow到endRow 共size条数据"
//当前页面第一个元素在数据库中的行号
private long startRow;

private long endRow;  //当前页面最后一个元素在数据库中的行号

private int pages;  //总页数
private int prePage;  //前一页
private int nextPage;  //下一页
private boolean isFirstPage = false;  //是否为第一页

private boolean isLastPage = false;   //是否为最后一页

private boolean hasPreviousPage = false;   //是否有前一页
private boolean hasNextPage = false;   //是否有下一页
private int navigatePages;  //导航页码数
private int[] navigatepageNums;  //所有导航页号
private int navigateFirstPage;  //导航条上的第一页
private int navigateLastPage;  //导航条上的最后一页

{
  "total": 12,
  "list": [
    {
      "deptno": 4,
      "dname": "事业部",
      "loc": "沙"
    },
    {
      "deptno": 3,
      "dname": "sales",
      "loc": "chicago"
    },
    {
      "deptno": 2,
      "dname": "research",
      "loc": "dallas"
    },
    {
      "deptno": 1,
      "dname": "IOS开发部",
      "loc": "长沙"
    }
  ],
  "pageNum": 3,
  "pageSize": 4,
  "size": 4,
  "startRow": 9,
  "endRow": 12,
  "pages": 3,
  "prePage": 2,
  "nextPage": 0,
  "isFirstPage": false,
  "isLastPage": true,
  "hasPreviousPage": true,
  "hasNextPage": false,
  "navigatePages": 8,
  "navigatepageNums": [
    1,
    2,
    3
  ],
  "navigateFirstPage": 1,
  "navigateLastPage": 3
}

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/88028
推荐阅读
相关标签
  

闽ICP备14008679号