我们已经知晓了Dialect至MySqlDialect的类继承结果,如下:
Dialect -> AbstractDialect -> AbstractHelperDialect -> MySqlDialect
并且已经知道了方法beforePage
方法定义与Dialect,实现在AbstractHelperDialect
中,判断SQL语句是否需要分页。
其中涉及到一个Page对象,beforePage中涉及到了Page对象是如何获取的呢?今天我们来看一下。
Page的获取
我们来看Page对象是如何在beforePage
获取的:
Page page = getLocalPage();
我们再来看getLocalPage
方法:
/** * 获取分页参数 * @param <T> * @return */ public <T> Page<T> getLocalPage() { return PageHelper.getLocalPage(); }
恩,继续深入查看:
/** * 获取 Page 参数 * @return */ public static <T> Page<T> getLocalPage() { return LOCAL_PAGE.get(); }
这里的 LOCAL_PAGE
是如何定义的呢?
/** * 基础分页方法 * @author liuzh */ public abstract class PageMethod { protected static final ThreadLocal<Page> LOCAL_PAGE = new ThreadLocal<Page>(); /** * 设置 Page 参数 * @param page */ protected static void setLocalPage(Page page) { LOCAL_PAGE.set(page); } }
这里的LOCAL_PAGE
是不是有些熟悉呢?
在文章《若依系统分页工具学习-PageHelper篇二》中,通过Controller中的方法startPage
的调用层次中,调用了PageMethod
中的startPage方法:
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 = getLocalPage(); if (oldPage != null && oldPage.isOrderByOnly()) { page.setOrderBy(oldPage.getOrderBy()); } setLocalPage(page); return page; } /** * 设置 Page 参数 * * @param page */ protected static void setLocalPage(Page page) { LOCAL_PAGE.set(page); }
如此便通过一个线程内部变量ThreadLocal<Page>
传过来了参数。
恩,这种传参方式没有深入理解的功力干不出来啊!反正我是不敢用~~
我们接着看 beforePage
方法中判断逻辑:
@Override public boolean beforePage(MappedStatement ms, Object parameterObject, RowBounds rowBounds) { Page page = getLocalPage(); if (page.isOrderByOnly() || page.getPageSize() > 0) { return true; } return false; }
如果分页参数的orderByOnly为true或者有pageSize大于0,则执行分页。
我们返回去看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); ....
这里缓存我们暂时不说。
看下一句调用的dialect方法:processParameterObject,注释为:“处理参数对象”,这个方法又在哪个类结构层次中呢?
最后发现它和beforePage一样,位于类AbstractHelperDialect中。
为了尽快查看SQL修改的具体位置我们暂时不对这个processParameterObject方法深入了解。