PageHelper用于查询语句分页,让分页更简单、代码更优雅。如果硬是要纠结效率与资源,那您倒是直接手写BaseDao哇....
集成mybatis-plus,代码中添加分页相关配置
/**
* mybatis-plus分页插件
* 文档:http://mp.baomidou.com
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor page = new PaginationInterceptor();
page.setDialectType("mysql");
// 打开PageHelper localPage 模式
page.setLocalPage(true);
return page;
}
这样就能使用PageHelper来分页了,当然要问了,为什么必须要手动设置打开呢?那就直接看源码咯~
直贴关键代码,具体源码请查阅:PaginationInterceptor.java
package com.baomidou.mybatisplus.plugins;
/**
*
* 分页拦截器
*
*
* @author hubin
* @Date 2016-01-23
*/
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class PaginationInterceptor implements Interceptor {
/* 是否开启 PageHelper localPage 模式 */
private boolean localPage = false;
/**
* Physical Pagination Interceptor for all the queries with parameter {@link org.apache.ibatis.session.RowBounds}
*/
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler statementHandler = (StatementHandler) PluginUtils.realTarget(invocation.getTarget());
MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler);
// 先判断是不是SELECT操作
MappedStatement mappedStatement = (MappedStatement) metaStatementHandler.getValue("delegate.mappedStatement");
if (!SqlCommandType.SELECT.equals(mappedStatement.getSqlCommandType())) {
return invocation.proceed();
}
RowBounds rowBounds = (RowBounds) metaStatementHandler.getValue("delegate.rowBounds");
/* 不需要分页的场合 */
if (rowBounds == null || rowBounds == RowBounds.DEFAULT) {
// 本地线程分页
if (localPage) {
// 采用ThreadLocal变量处理的分页
rowBounds = PageHelper.getPagination();
if (rowBounds == null) {
return invocation.proceed();
}
} else {
// 无需分页
return invocation.proceed();
}
}
// 针对定义了rowBounds,做为mapper接口方法的参数
BoundSql boundSql = (BoundSql) metaStatementHandler.getValue("delegate.boundSql");
String originalSql = boundSql.getSql();
Connection connection = (Connection) invocation.getArgs()[0];
DBType dbType = StringUtils.isNotEmpty(dialectType) ? DBType.getDBType(dialectType) : JdbcUtils.getDbType(connection.getMetaData().getURL());
if (rowBounds instanceof Pagination) {
Pagination page = (Pagination) rowBounds;
boolean orderBy = true;
if (page.isSearchCount()) {
SqlInfo sqlInfo = SqlUtils.getCountOptimize(sqlParser, originalSql);
orderBy = sqlInfo.isOrderBy();
this.queryTotal(overflowCurrent, sqlInfo.getSql(), mappedStatement, boundSql, page, connection);
if (page.getTotal() <= 0) {
return invocation.proceed();
}
}
String buildSql = SqlUtils.concatOrderBy(originalSql, page, orderBy);
originalSql = DialectFactory.buildPaginationSql(page, buildSql, dbType, dialectClazz);
} else {
// support physical Pagination for RowBounds
originalSql = DialectFactory.buildPaginationSql(rowBounds, originalSql, dbType, dialectClazz);
}
/*
* 禁用内存分页
* 内存分页会查询所有结果出来处理(这个很吓人的),如果结果变化频繁这个数据还会不准。
*/
metaStatementHandler.setValue("delegate.boundSql.sql", originalSql);
metaStatementHandler.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET);
metaStatementHandler.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT);
return invocation.proceed();
}
public void setLocalPage(boolean localPage) {
this.localPage = localPage;
}
}
关键地方已标红,在PaginationInterceptor中,是否开启 PageHelper localPage 模式,默认是关闭的,需要手动打开
/* 是否开启 PageHelper localPage 模式 */
private boolean localPage = false;
这货为啥不是默认打开呢?查看PageHelper类可以发现,是基于ThreadLocal实现,了然。
public class PageHelper {
// 分页本地线程变量
private static final ThreadLocal LOCAL_PAGE = new ThreadLocal<>();
/**
*
* 获取分页
*
*
* @return
*/
public static Pagination getPagination() {
return LOCAL_PAGE.get();
}
/**
*
* 设置分页
*
*
* @param page
*/
public static void setPagination(Pagination page) {
LOCAL_PAGE.set(page);
}
好,接下来使用就方便了
// 组装查询条件
EntityWrapper wrapper = new EntityWrapper<>();
if (null != status) {
wrapper.eq("status", status);
}
// 设置分页参数
PageHelper.startPage(pageIndex, pageSize);
// 执行查询
List platfProjects = UserMapper.selectList(wrapper);
// 返回的分页参数
Pagination pagination = PageHelper.getPagination();
就是这样~