Mybatis 分页:Pagehelper + 拦截器实现

一、分页插件 Pagehelper

PageHelper是Mybatis的一个分页插件,非常好用!

1.1 Spring Boot 依赖 <!-- pagehelper 分页插件--> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.2.12</version> </dependency>

也可以这么引入

<dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>latest version</version> </dependency> 1.2 PageHelper 配置

配置文件增加PageHelper的配置,主要设置了分页方言和支持接口参数传递分页参数,如下:

pagehelper: # 指定数据库 helper-dialect: mysql # 默认是false。启用合理化时,如果pageNum<1会查询第一页,如果pageNum>pages(最大页数)会查询最后一页。禁用合理化时,如果pageNum<1或pageNum>pages会返回空数据 reasonable: false # 是否支持接口参数来传递分页参数,默认false support-methods-arguments: true # 为了支持startPage(Object params)方法,增加了该参数来配置参数映射,用于从对象中根据属性名取值, 可以配置 pageNum,pageSize,count,pageSizeZero,reasonable,不配置映射的用默认值, 默认值为pageNum=pageNum;pageSize=pageSize;count=countSql;reasonable=reasonable;pageSizeZero=pageSizeZero params: count=countSql row-bounds-with-count: true

项目完整配置文件详见文mybatis-pagehelper。

1.3 如何分页

只有紧跟在PageHelper.startPage方法后的第一个Mybatis的查询(Select)方法会自动分页!!!!

@Test public void selectForPage() { // 第几页 int currentPage = 2; // 每页数量 int pageSize = 5; // 排序 String orderBy = "id desc"; PageHelper.startPage(currentPage, pageSize, orderBy); List<UserInfoPagehelperDO> users = userInfoPagehelperMapper.selectList(); PageInfo<UserInfoPagehelperDO> userPageInfo = new PageInfo<>(users); log.info("userPageInfo:{}", userPageInfo); } ...: userPageInfo:PageInfo{pageNum=2, pageSize=5, size=1, startRow=6, endRow=6, total=6, pages=2, list=Page{count=true, pageNum=2, pageSize=5, startRow=5, endRow=10, total=6, pages=2, reasonable=false, pageSizeZero=false}[UserInfoPagehelperDO{id=1, userName='null', age=22, createTime=null}], prePage=1, nextPage=0, isFirstPage=false, isLastPage=true, hasPreviousPage=true, hasNextPage=false, navigatePages=8, navigateFirstPage=1, navigateLastPage=2, navigatepageNums=[1, 2]}

这里的返回结果包括数据、是否为第一页/最后一页、总页数、总记录数,详见Mybatis-PageHelper

Pagehelper 分页完整示例

二、Mybatis 拦截器实现分页 2.1 Mybatis 拦截器

【插件】部分有以下描述:

通过 MyBatis 提供的强大机制,使用插件是非常简单的,只需实现 Interceptor 接口,并指定想要拦截的方法签名即可。

MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:

Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed) ParameterHandler (getParameterObject, setParameters) ResultSetHandler (handleResultSets, handleOutputParameters) StatementHandler (prepare, parameterize, batch, update, query)

即:我们可以通过拦截器的方式,实现MyBatis插件(数据分页)

接下来重点演示我如何使用了拦截器实现分页。

2.2 调用形式

在看如何实现之前,我们先看看如何使用:

照抄 PageHelper 的设计,先调用一个静态方法,对下面第一个方法的sql语句进行拦截,在new一个分页对象时自动处理。

@Test public void selectForPage() { // 该查询进行分页,指定第几页和每页数量 PageInterceptor.startPage(1,2); List<UserInfoDO> all = dao.findAll(); PageResult<UserInfoDO> result = new PageResult<>(all); // 分页结果打印 System.out.println("总记录数:" + result.getTotal()); System.out.println(result.getData().toString()); }

然后我们主要看看实现步骤。

2.3 数据库方言

定义好一个方言接口,不同的数据使用不同的方言实现

Dialect.java

public interface Dialect { /** * 获取count SQL语句 * * @param targetSql * @return */ default String getCountSql(String targetSql) { return String.format("select count(1) from (%s) tmp_count", targetSql); } /** * 获取limit SQL语句 * @param targetSql * @param offset * @param limit * @return */ String getLimitSql(String targetSql, int offset, int limit); }

Mysql 分页方言

@Component public class MysqlDialect implements Dialect{ private static final String PATTERN = "%s limit %s, %s"; private static final String PATTERN_FIRST = "%s limit %s"; @Override public String getLimitSql(String targetSql, int offset, int limit) { if (offset == 0) { return String.format(PATTERN_FIRST, targetSql, limit); } return String.format(PATTERN, targetSql, offset, limit); } } 2.4 拦截器核心逻辑

该部分完整代码见 PageInterceptor.java

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpxfyj.html