MyBatis 分页插件 PageHelper 使用说明

目录

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 GitHub:GitHub - 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 启动器:

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

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

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

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

//控制层方法:http://localhost:8080/findByKeywordPage1?pageNum=2&pageSize=4
@GetMapping("/findByKeywordPage1")
public PageInfo findByKeywordPage1(String keyword, Integer pageNum, Integer pageSize) {
	pageNum = pageNum == null || pageNum <= 0 ? 0 : pageNum;
	pageSize = pageSize == null || pageSize <= 0L ? 0 : pageSize;
	/**
	 * 1、PageHelper.startPage(int pageNum, int pageSize):开始分页,此时 XxxMapper 返回的集合是 {@link com.github.pagehelper.Page} 分页对象
	 * total(总记录数) 等于 ((Page)list).getTotal();
	 * 2、PageHelper.offsetPage:开始分页,底层与 startPage 是一样的.
	 * 3、如果 pageNum 或者 pageSize 为 0,则不分页,默认查询所有,此时 XxxMapper 返回的集合不再是 {@link com.github.pagehelper.Page} 分页对象
	 * 此时 size(当前页的数量)、total(总记录数) 都是等于普通的 list.size()
	 * 4、只有紧跟在 PageHelper.startPage、PageHelper.offsetPage 方法后的第一个 Mybatis 的查询(Select)方法会被分页。
	 */
	if (pageNum != 0 && pageSize != 0) {
		//PageHelper.startPage(pageNum, pageSize);
		PageHelper.offsetPage(pageNum, pageSize);
	}
	List<Dept> deptList = deptMapper.findByKeyword(keyword);

	/**
	 * PageInfo(List<T> list):包装 Page 对象,默认导航页码为8
	 * PageInfo(List<T> list, int navigatePages):包装 Page 对象,指定导航页码数量
	 */
	PageInfo pageInfo = new PageInfo(deptList);
	return pageInfo;
}
//DeptMapper 接口:根据关键字模糊查询,默认查询所有
List<Dept> findByKeyword(String keyword);
<!-- DeptMapper.xml 映射 -->
<!-- 根据关键字模糊查询,不为空时才拼 like 条件,否则默认查询所有.-->
<select id="findByKeyword" resultType="com.wmx.hb.pojo.Dept" parameterType="string">
	select * from dept
	<where>
		<if test="keyword!=null">
			dname like concat('%',concat(#{keyword},'%')) or loc like concat('%',concat(#{keyword},'%'))
		</if>
	</where>
	order by deptno desc
</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 方法参数分页.

//控制层方法
@PostMapping("/findByDept")
public PageInfo<Dept> findByDept(@RequestBody(required = false) Dept dept, Integer pageNum, Integer pageSize) {
	pageNum = pageNum == null || pageNum <= 0L ? 1 : pageNum;
	pageSize = pageSize == null || pageSize <= 0L ? 2 : pageSize;

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

ISelect 接口方式分页

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

//控制层方法
@GetMapping("/findByKeyword")
public PageInfo<Dept> findByKeyword(String keyword, Integer pageNum, Integer pageSize) {
	pageNum = pageNum == null || pageNum <= 0 ? 0 : pageNum;
	pageSize = pageSize == null || pageSize <= 0L ? 0 : pageSize;

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蚩尤后裔-汪茂雄

芝兰生于深林,不以无人而不芳。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值