问题描述
业务中同时使用「查总条数」和「分页查询」场景,均启用asyncCount=true:
查总条数时设置pageSize=0(预期:仅触发count,不查询数据);
分页查询时设置pageSize>0(预期:正常分页)。
但发现异步count模式下,pageSize=0时未像同步count那样提前终止流程,反而执行了不必要的数据查询。
复现代码
// 场景1:查总条数(预期:仅异步count,不查数据)
Integer pageSize = 0;
PageHelper.startPage(currentPage, pageSize).asyncCount(true);
// 场景2:分页查询(预期:异步count+分页查询)
Integer pageSize = 50;
PageHelper.startPage(currentPage, pageSize).asyncCount(true);
问题分析
通过源码跟踪,发现同步/异步count的流程差异:
同步count流程(正常)
PageInterceptor#intercept:
if (dialect.beforeCount(ms, parameter, rowBounds)) {
if (dialect.isAsyncCount()) {
countFuture = asyncCount(ms, boundSql, parameter, rowBounds);
} else {
//查询总数
Long count = count(executor, ms, parameter, rowBounds, null, boundSql);
//处理查询总数,返回 true 时继续分页查询,false 时直接返回
if (!dialect.afterCount(count, parameter, rowBounds)) {
//当查询总数为 0 时,直接返回空的结果 <<<< pageSize=0直接返回空结果
return dialect.afterPage(new ArrayList(), parameter, rowBounds);
}
}
}
// >>>> 仅count>0时才走分页查询
resultList = ExecutorUtil.pageQuery(dialect, executor, ms, parameter, rowBounds, resultHandler, boundSql, cacheKey);
异步count流程(异常)
PageInterceptor#intercept:
if (dialect.beforeCount(ms, parameter, rowBounds)) {
if (dialect.isAsyncCount()) {
countFuture = asyncCount(ms, boundSql, parameter, rowBounds);
} else {
...
}
}
// >>>> 异步count时,直接执行分页查询
resultList = ExecutorUtil.pageQuery(dialect, executor, ms, parameter, rowBounds, resultHandler, boundSql, cacheKey);
ExecutorUtil#pageQuery:
//判断是否需要进行分页查询
if (dialect.beforePage(ms, parameter, rowBounds)) { <<<< 调用dialect.beforePage判断是否需要分页
...
//执行分页查询
return executor.query(ms, parameter, RowBounds.DEFAULT, resultHandler, pageKey, pageBoundSql);
} else {
//不执行分页的情况下,也不执行内存分页
return executor.query(ms, parameter, RowBounds.DEFAULT, resultHandler, cacheKey, boundSql);
}
AbstractHelperDialect#beforePage:
public boolean beforePage(MappedStatement ms, Object parameterObject, RowBounds rowBounds) {
Page page = getLocalPage();
if (page.isOrderByOnly() || page.getPageSize() > 0) { <<<< pageSize为0, 返回false, 导致不执行分页逻辑
return true;
}
return false;
}
异步count模式下,业务设置了pageSize=0,会执行不分页的全量数据查询
问题描述
业务中同时使用「查总条数」和「分页查询」场景,均启用asyncCount=true:
查总条数时设置pageSize=0(预期:仅触发count,不查询数据);
分页查询时设置pageSize>0(预期:正常分页)。
但发现异步count模式下,pageSize=0时未像同步count那样提前终止流程,反而执行了不必要的数据查询。
复现代码
问题分析
通过源码跟踪,发现同步/异步count的流程差异:
同步count流程(正常)
PageInterceptor#intercept:异步count流程(异常)
PageInterceptor#intercept:ExecutorUtil#pageQuery:AbstractHelperDialect#beforePage:异步count模式下,业务设置了pageSize=0,会执行不分页的全量数据查询