这是我参与11月更文挑战的第18天,活动详情查看:2021最后一次更文挑战
在昨天的文章中我们通过研究PageInterceptor
拦截器,发现了其中的一个可配置接口Dialect
,进而找出来其可通过java.util.Properties
来配置实现类从而适配不同的数据库形式,如适配mysql, Oracle等等。
今天,我们紧接着上次查看到的位于ExecutorUtil
中的query
方法。
我们已经知道dialect在我们的使用场景-若依系统下是mysql的,也就是其对应的是MySqlDialect
。我们依次看看分页方法中调用的实现位于哪里?
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)) {
//....
}
复制代码
第一句,判断是否需要进行分页查询,调用了dialect.beforePage
方法,我们这次需要逆向的从MySqlDialect
找其实现代码在哪里?
MySqlDialect的层次结构
经过梳理MySqlDialect
的层次如下所示:
Dialect -> AbstractDialect -> AbstractHelperDialect -> MySqlDialect
从各个方法的注释我们来看:
- 接口 Dialect: 数据库方言,针对不同数据库进行实现;
- 抽象类 AbstractDialect:基于 CountSqlParser 的智能 Count 查询;
- 抽象类 AbstractHelperDialect: 针对 PageHelper 的实现;
- 实现类 MySqlDialect: 针对mysql数据库的具体实现。
其中方法beforePage(...)
的定义与实现是位于哪里呢?既然在调用时是以Dialect调用的,因此我们知道,定义肯定是位于最高层接口Dialect中,那么实现又在哪里呢?
通过逐层查找,beforePage(...)
位于第三层类AbstractHelperDialect中。代码如下:
@Override
public boolean beforePage(MappedStatement ms, Object parameterObject, RowBounds rowBounds) {
Page page = getLocalPage();
if (page.isOrderByOnly() || page.getPageSize() > 0) {
return true;
}
return false;
}
复制代码
其中的Page是Mybatis的分页对象,通过判断其中的isOrderByOnly
与pageSize
参数判断SQL是否需要分页,如果需要分页则返回true
,不需要分页则返回false
。
Page
的几个变量与注释如下:
public class Page<E> extends ArrayList<E> implements Closeable {
private static final long serialVersionUID = 1L;
private int pageNum;
private int pageSize;
private long startRow;
private long endRow;
private long total;
/**
* 总页数
*/
private int pages;
/**
* 包含count查询
*/
private boolean count = true;
/**
* 分页合理化
*/
private Boolean reasonable;
/**
* 当设置为true的时候,如果pagesize设置为0(或RowBounds的limit=0),就不执行分页,返回全部结果
*/
private Boolean pageSizeZero;
/**
* 进行count查询的列名
*/
private String countColumn;
/**
* 排序
*/
private String orderBy;
/**
* 只增加排序
*/
private boolean orderByOnly;
复制代码
那么这个Page参数又是何时设置的呢?其中的orderByOnly
与pageSize
是通过何种逻辑设置,又是如何在此处获取到该SQL执行时的Page对象的呢?