Spring Boot 整合 PageHelper

在 PageHelper官网,对PageHelper进行了如下描述

Spring Boot 整合 PageHelper_第1张图片

 

如何在Spring Boot项目当中引入PageHelper进行分页处理呢?

第一步:添加maven依赖


	com.github.pagehelper
	pagehelper-spring-boot-starter
	1.2.3

第二步:添加properties配置

#pagehelper分页插件配置
pagehelper.helper-dialect=mysql
pagehelper.reasonable=true
pagehelper.support-methods-arguments=true
pagehelper.params=count=countSql

第三步:在你的查询语句之前进行分页处理

//第几页
Integer pageNum = 1;
//一页多少数据
Integer pageSize = 10;
//开始分页
PageHelper.startPage(pageNum,pageSize);
//查询语句
studentService.selectAll();

通过以上三步,就已经实现了分页处理了。

 

那么,PageHelper是如何实现分页处理的呢?

PageHelper分页原理

第一步:我们首先得理解mybatis的plugin,可以在mybatis官方文档当中,找到如下描述

Spring Boot 整合 PageHelper_第2张图片

那么,我们可否实现自己的plugin,来打印需要执行的sql语句呢?

可以

比如我们先按照文档,写一个MyPlugin

@Intercepts({@Signature(
        type= StatementHandler.class,
        method = "prepare",
        args = {Connection.class,Integer.class})})
public class MyPlugin implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler statementHandler= (StatementHandler) invocation.getTarget();
        BoundSql boundSql = statementHandler.getBoundSql();
        //打印sql语句
        System.out.println("MyPlugin" + boundSql.getSql());
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target,this);
    }

    @Override
    public void setProperties(Properties properties) {
        String dialect = properties.getProperty("dialect");
        System.out.println("dialect="+dialect);
    }
}

  然后在springboot当中注册成Bean

@Bean
public MyPlugin myPlugin(){
        MyPlugin myPlugin = new MyPlugin();
	Properties properties = new Properties();
	properties.setProperty("dialect","mysql");
	myPlugin.setProperties(properties);
	return myPlugin;
}

通过上面的两步我们就实现了一个自己的Plugin,来打印出需要执行的sql语句

第二步:通过上面文档的描述,我们知道,mybatis的插件就像springmvc当中的Interceptor,可以对方法进行拦截。那么既然可以对方法进行拦截,那么我可不可以,在每个查询方法之前,先检测一下当前语句是否需要分页,假如需要分页,我就拼接分页的SQL语句,然后再执行拼接后的SQL语句呢?

可以,因为PageHelper就是这样做的

在PageHelper分页当中,首先要执行startPage方法

//通过startPage,把当前的分页信息保存到ThreadLocal里面,确保每个线程之间互不影响
public static  Page startPage(int pageNum, int pageSize,
 boolean count, Boolean reasonable, Boolean pageSizeZero) {
        Page page = new Page(pageNum, pageSize, count);
        page.setReasonable(reasonable);
        page.setPageSizeZero(pageSizeZero);
        Page oldPage = getLocalPage();
        if (oldPage != null && oldPage.isOrderByOnly()) {
            page.setOrderBy(oldPage.getOrderBy());
        }
        //把信息保存到ThreadLocal里面
        setLocalPage(page);
        return page;
    }
然后可以查看到com.github.pagehelper.PageInterceptor,一个PageHelper的Plugin。

我们在PageInterceptor.intercept这个拦截方法当中,可以找到如下两个语句

String pageSql = this.dialect.getPageSql(ms, boundSql, parameter, rowBounds, cacheKey);
BoundSql pageBoundSql = new BoundSql(configuration, pageSql, boundSql.getParameterMappings(), parameter);

 其中,getPageSql根据每种数据库而不同,以MySQL数据库为例,它的getPageSql语句如下:

public String getPageSql(String sql, Page page, CacheKey pageKey) {
        StringBuilder sqlBuilder = new StringBuilder(sql.length() + 14);
        sqlBuilder.append(sql);
        //在这里,进行分页语句拼接
        if (page.getStartRow() == 0) {
            sqlBuilder.append(" LIMIT ? ");
        } else {
            sqlBuilder.append(" LIMIT ?, ? ");
        }
        pageKey.update(page.getPageSize());
        return sqlBuilder.toString();
    }

到此,我们就知道了PageHelper如何分页

1、通过startPage方法,把当前的分页参数保存到ThreadLocal LOCAL_PAGE这个参数当中

2、通过com.github.pagehelper.PageInterceptor拦截要执行的query方法

3、根据dialect信息,执行不同数据库的getPageSql方法,拼接分页语句

4、拦截器执行getPageSql返回的新的sql语句,进行分页查询

你可能感兴趣的:(SpringBoot)