PageHelper是什么
基于mybatis的一款分页插件,仅用少量代码即可实现分页功能
查询数量sql怎么生成的
修改了原生的sqlSource,产生了count的MappedStatement
public static MappedStatement newCountMappedStatement(MappedStatement ms) {
MappedStatement.Builder builder = new MappedStatement.Builder(ms.getConfiguration(), ms.getId() + "_COUNT", ms.getSqlSource(), ms.getSqlCommandType());
builder.resource(ms.getResource());
builder.fetchSize(ms.getFetchSize());
builder.statementType(ms.getStatementType());
builder.keyGenerator(ms.getKeyGenerator());
if (ms.getKeyProperties() != null && ms.getKeyProperties().length != 0) {
StringBuilder keyProperties = new StringBuilder();
for (String keyProperty : ms.getKeyProperties()) {
keyProperties.append(keyProperty).append(",");
}
keyProperties.delete(keyProperties.length() - 1, keyProperties.length());
builder.keyProperty(keyProperties.toString());
}
builder.timeout(ms.getTimeout());
builder.parameterMap(ms.getParameterMap());
//count查询返回值int
List<ResultMap> resultMaps = new ArrayList<ResultMap>();
ResultMap resultMap = new ResultMap.Builder(ms.getConfiguration(), ms.getId(), int.class, EMPTY_RESULTMAPPING).build();
resultMaps.add(resultMap);
builder.resultMaps(resultMaps);
builder.resultSetType(ms.getResultSetType());
builder.cache(ms.getCache());
builder.flushCacheRequired(ms.isFlushCacheRequired());
builder.useCache(ms.isUseCache());
return builder.build();
}
分页sql怎么产生的
对于不同的数据源做不同的处理,对mysql而言,就是产生了对应的limit语句
public class MysqlParser extends AbstractParser {
@Override
public String getPageSql(String sql) {
StringBuilder sqlBuilder = new StringBuilder(sql.length() + 14);
sqlBuilder.append(sql);
sqlBuilder.append(" limit ?,?");
return sqlBuilder.toString();
}
@Override
public Map<String, Object> setPageParameter(MappedStatement ms, Object parameterObject, BoundSql boundSql, Page<?> page) {
Map<String, Object> paramMap = super.setPageParameter(ms, parameterObject, boundSql, page);
paramMap.put(PAGEPARAMETER_FIRST, page.getStartRow());
paramMap.put(PAGEPARAMETER_SECOND, page.getPageSize());
return paramMap;
}
}
分页参数怎么保存的
通过startPage方法,将分页参数放到ThreadLocal中
public static <E> Page<E> startPage(int pageNum, int pageSize, boolean count, Boolean reasonable, Boolean pageSizeZero) {
Page<E> page = new Page<E>(pageNum, pageSize, count);
page.setReasonable(reasonable);
page.setPageSizeZero(pageSizeZero);
//当已经执行过orderBy的时候
Page<E> oldPage = SqlUtil.getLocalPage();
if (oldPage != null && oldPage.isOrderByOnly()) {
page.setOrderBy(oldPage.getOrderBy());
}
SqlUtil.setLocalPage(page);
return page;
}
插件如何融于mybatis中
通过注册mybatis插件,PageHelper实现了Interceptor接口,核心的处理逻辑都在intercept方法中
/**
* Mybatis拦截器方法
*
* @param invocation 拦截器入参
* @return 返回执行结果
* @throws Throwable 抛出异常
*/
public Object intercept(Invocation invocation) throws Throwable {
if (autoRuntimeDialect) {
SqlUtil sqlUtil = getSqlUtil(invocation);
return sqlUtil.processPage(invocation);
} else {
if (autoDialect) {
initSqlUtil(invocation);
}
return sqlUtil.processPage(invocation);
}
}
sqlSource的动态判断
public void processMappedStatement(MappedStatement ms) throws Throwable {
SqlSource sqlSource = ms.getSqlSource();
MetaObject msObject = SystemMetaObject.forObject(ms);
SqlSource pageSqlSource;
if (sqlSource instanceof StaticSqlSource) {
pageSqlSource = new PageStaticSqlSource((StaticSqlSource) sqlSource);
} else if (sqlSource instanceof RawSqlSource) {
pageSqlSource = new PageRawSqlSource((RawSqlSource) sqlSource);
} else if (sqlSource instanceof ProviderSqlSource) {
pageSqlSource = new PageProviderSqlSource((ProviderSqlSource) sqlSource);
} else if (sqlSource instanceof DynamicSqlSource) {
pageSqlSource = new PageDynamicSqlSource((DynamicSqlSource) sqlSource);
} else {
throw new RuntimeException("无法处理该类型[" + sqlSource.getClass() + "]的SqlSource");
}
msObject.setValue("sqlSource", pageSqlSource);
//由于count查询需要修改返回值,因此这里要创建一个Count查询的MS
msCountMap.put(ms.getId(), MSUtils.newCountMappedStatement(ms));
}
parser的动态判断
从sql链接中获取方言,例如mysql,通过mysql判断
public static Parser newParser(Dialect dialect) {
Parser parser = null;
switch (dialect) {
case mysql:
case mariadb:
case sqlite:
parser = new MysqlParser();
break;
case oracle:
parser = new OracleParser();
break;
case hsqldb:
parser = new HsqldbParser();
break;
case sqlserver:
parser = new SqlServerParser();
break;
case sqlserver2012:
parser = new SqlServer2012Dialect();
break;
case db2:
parser = new Db2Parser();
break;
case postgresql:
parser = new PostgreSQLParser();
break;
case informix:
parser = new InformixParser();
break;
case h2:
parser = new H2Parser();
break;
default:
throw new RuntimeException("分页插件" + dialect + "方言错误!");
}
return parser;
}