我们在AbstractHelperDialect.beforePage
方法中发现了一个变量Page
,并且知道了PageHelper是通过ThreadLocal<Page>
来将其作为线程局部变量来巧妙的传递的。
今天我们接着看在通过beforePage
方法判断需要分页后,程序又执行了哪些逻辑?
接着看ExecutorUtil类的pageQuery方法:
public static <E> List<E> pageQuery(Dialect dialect, Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql, CacheKey cacheKey) throws SQLException { //判断是否需要进行分页查询 if (dialect.beforePage(ms, parameter, rowBounds)) { //生成分页的缓存 key CacheKey pageKey = cacheKey; //处理参数对象 parameter = dialect.processParameterObject(ms, parameter, boundSql, pageKey); // ....其他代码暂时不贴 }
下一行代码注释为生成分页的缓存key,之间将参数cacheKey赋值给局部变量pageKey,不多阐述。
紧接着下一行:
//处理参数对象 parameter = dialect.processParameterObject(ms, parameter, boundSql, pageKey);
这一行代码调用dialect处理参数方法处理parameter并且将返回值重新赋值给parameter参数。
我们来细细的看一下其中的参数处理逻辑。
通过前几篇文章,我们知道MysqlDialect的类层次结构:
Dialect -> AbstractDialect -> AbstractHelperDialect -> MySqlDialect
我们在最近的一层发现 AbstractHelperDialect
中有其实现:
@Override public Object processParameterObject(MappedStatement ms, Object parameterObject, BoundSql boundSql, CacheKey pageKey) { //处理参数 // 具体代码.... }
我们逐行查看其处理逻辑:
//处理参数 Page page = getLocalPage(); //如果只是 order by 就不必处理参数 if (page.isOrderByOnly()) { return parameterObject; }
这里有一个奇怪的点或者也可能是代码风格,通过检索
orderByOnly
我没有发现在什么情况下会设置其为false的代码逻辑,换句话说,目前orderByOnly默认值为false,而调用setOrderByOnly的情况只有setOrderByOnly(true)
接着往下看:
Map<String, Object> paramMap = null; if (parameterObject == null) { paramMap = new HashMap<String, Object>(); } else if (parameterObject instanceof Map) { //解决不可变Map的情况 paramMap = new HashMap<String, Object>(); paramMap.putAll((Map) parameterObject); } else { /// 其他情况代码.....省略 } return processPageParameter(ms, paramMap, page, boundSql, pageKey);
前面两种if处理参数为空以及参数为map的情况。
下面代码涉及到多个参数相关的类,暂时不多解释。我们最关心的仍然是sql修改。