mirror of
https://gitee.com/mybatis-flex/mybatis-flex.git
synced 2025-12-08 09:38:26 +08:00
refactor: 优化分页查询代码。
This commit is contained in:
parent
6034a49116
commit
209ec6ab60
@ -20,7 +20,10 @@ import com.mybatisflex.core.field.FieldQueryBuilder;
|
|||||||
import com.mybatisflex.core.mybatis.MappedStatementTypes;
|
import com.mybatisflex.core.mybatis.MappedStatementTypes;
|
||||||
import com.mybatisflex.core.paginate.Page;
|
import com.mybatisflex.core.paginate.Page;
|
||||||
import com.mybatisflex.core.provider.EntitySqlProvider;
|
import com.mybatisflex.core.provider.EntitySqlProvider;
|
||||||
import com.mybatisflex.core.query.*;
|
import com.mybatisflex.core.query.CPI;
|
||||||
|
import com.mybatisflex.core.query.QueryColumn;
|
||||||
|
import com.mybatisflex.core.query.QueryCondition;
|
||||||
|
import com.mybatisflex.core.query.QueryWrapper;
|
||||||
import com.mybatisflex.core.table.TableInfo;
|
import com.mybatisflex.core.table.TableInfo;
|
||||||
import com.mybatisflex.core.table.TableInfoFactory;
|
import com.mybatisflex.core.table.TableInfoFactory;
|
||||||
import com.mybatisflex.core.util.*;
|
import com.mybatisflex.core.util.*;
|
||||||
@ -667,47 +670,39 @@ public interface BaseMapper<T> {
|
|||||||
|
|
||||||
|
|
||||||
default <R> Page<R> paginateAs(Page<R> page, QueryWrapper queryWrapper, Class<R> asType, Consumer<FieldQueryBuilder<R>>... consumers) {
|
default <R> Page<R> paginateAs(Page<R> page, QueryWrapper queryWrapper, Class<R> asType, Consumer<FieldQueryBuilder<R>>... consumers) {
|
||||||
List<QueryColumn> selectColumns = CPI.getSelectColumns(queryWrapper);
|
try {
|
||||||
List<QueryOrderBy> orderBys = CPI.getOrderBys(queryWrapper);
|
// 只有 totalRow 小于 0 的时候才会去查询总量
|
||||||
List<Join> joins = CPI.getJoins(queryWrapper);
|
// 这样方便用户做总数缓存,而非每次都要去查询总量
|
||||||
// 只有 totalRow 小于 0 的时候才会去查询总量
|
// 一般的分页场景中,只有第一页的时候有必要去查询总量,第二页以后是不需要的
|
||||||
// 这样方便用户做总数缓存,而非每次都要去查询总量
|
if (page.getTotalRow() < 0) {
|
||||||
// 一般的分页场景中,只有第一页的时候有必要去查询总量,第二页以后是不需要的
|
QueryWrapper countQueryWrapper = MapperUtil.optimizeCountQueryWrapper(queryWrapper);
|
||||||
if (page.getTotalRow() < 0) {
|
page.setTotalRow(selectCountByQuery(countQueryWrapper));
|
||||||
QueryWrapper countQueryWrapper = MapperUtil.optimizeCountQueryWrapper(queryWrapper);
|
}
|
||||||
long count = selectCountByQuery(countQueryWrapper);
|
|
||||||
page.setTotalRow(count);
|
if (page.isEmpty()) {
|
||||||
}
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
|
int offset = page.getPageSize() * (page.getPageNumber() - 1);
|
||||||
|
queryWrapper.limit(offset, page.getPageSize());
|
||||||
|
|
||||||
|
List<R> records;
|
||||||
|
if (asType != null) {
|
||||||
|
records = selectListByQueryAs(queryWrapper, asType);
|
||||||
|
} else {
|
||||||
|
records = (List<R>) selectListByQuery(queryWrapper);
|
||||||
|
}
|
||||||
|
MapperUtil.queryFields(this, records, consumers);
|
||||||
|
page.setRecords(records);
|
||||||
|
|
||||||
if (page.isEmpty()) {
|
|
||||||
return page;
|
return page;
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
// 将之前设置的 limit 清除掉
|
||||||
|
// 保险起见把重置代码放到 finally 代码块中
|
||||||
|
CPI.setLimitRows(queryWrapper, null);
|
||||||
|
CPI.setLimitOffset(queryWrapper, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
//重置 selectColumns
|
|
||||||
CPI.setSelectColumns(queryWrapper, selectColumns);
|
|
||||||
//重置 orderBys
|
|
||||||
CPI.setOrderBys(queryWrapper, orderBys);
|
|
||||||
//重置 join
|
|
||||||
CPI.setJoins(queryWrapper, joins);
|
|
||||||
|
|
||||||
int offset = page.getPageSize() * (page.getPageNumber() - 1);
|
|
||||||
queryWrapper.limit(offset, page.getPageSize());
|
|
||||||
|
|
||||||
if (asType != null) {
|
|
||||||
List<R> records = selectListByQueryAs(queryWrapper, asType);
|
|
||||||
MapperUtil.queryFields(this, records, consumers);
|
|
||||||
page.setRecords(records);
|
|
||||||
} else {
|
|
||||||
List<R> records = (List<R>) selectListByQuery(queryWrapper);
|
|
||||||
MapperUtil.queryFields(this, records, consumers);
|
|
||||||
page.setRecords(records);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将之前设置的 limit 清除掉
|
|
||||||
CPI.setLimitRows(queryWrapper, null);
|
|
||||||
CPI.setLimitOffset(queryWrapper, null);
|
|
||||||
|
|
||||||
return page;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -19,7 +19,9 @@ import com.mybatisflex.core.FlexConsts;
|
|||||||
import com.mybatisflex.core.exception.FlexExceptions;
|
import com.mybatisflex.core.exception.FlexExceptions;
|
||||||
import com.mybatisflex.core.paginate.Page;
|
import com.mybatisflex.core.paginate.Page;
|
||||||
import com.mybatisflex.core.provider.RowSqlProvider;
|
import com.mybatisflex.core.provider.RowSqlProvider;
|
||||||
import com.mybatisflex.core.query.*;
|
import com.mybatisflex.core.query.CPI;
|
||||||
|
import com.mybatisflex.core.query.QueryColumn;
|
||||||
|
import com.mybatisflex.core.query.QueryWrapper;
|
||||||
import com.mybatisflex.core.util.CollectionUtil;
|
import com.mybatisflex.core.util.CollectionUtil;
|
||||||
import com.mybatisflex.core.util.MapperUtil;
|
import com.mybatisflex.core.util.MapperUtil;
|
||||||
import com.mybatisflex.core.util.StringUtil;
|
import com.mybatisflex.core.util.StringUtil;
|
||||||
@ -431,47 +433,35 @@ public interface RowMapper {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
default Page<Row> paginate(String schema, String tableName, Page<Row> page, QueryWrapper queryWrapper) {
|
default Page<Row> paginate(String schema, String tableName, Page<Row> page, QueryWrapper queryWrapper) {
|
||||||
|
try {
|
||||||
|
CPI.setFromIfNecessary(queryWrapper, schema, tableName);
|
||||||
|
|
||||||
CPI.setFromIfNecessary(queryWrapper, schema, tableName);
|
// 只有 totalRow 小于 0 的时候才会去查询总量
|
||||||
|
// 这样方便用户做总数缓存,而非每次都要去查询总量
|
||||||
|
// 一般的分页场景中,只有第一页的时候有必要去查询总量,第二页以后是不需要的
|
||||||
|
if (page.getTotalRow() < 0) {
|
||||||
|
QueryWrapper countQueryWrapper = MapperUtil.optimizeCountQueryWrapper(queryWrapper);
|
||||||
|
page.setTotalRow(selectCountByQuery(schema, tableName, countQueryWrapper));
|
||||||
|
}
|
||||||
|
|
||||||
List<QueryColumn> selectColumns = CPI.getSelectColumns(queryWrapper);
|
if (page.isEmpty()) {
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
List<QueryOrderBy> orderBys = CPI.getOrderBys(queryWrapper);
|
int offset = page.getPageSize() * (page.getPageNumber() - 1);
|
||||||
|
queryWrapper.limit(offset, page.getPageSize());
|
||||||
|
|
||||||
List<Join> joins = CPI.getJoins(queryWrapper);
|
page.setRecords(selectListByQuery(schema, tableName, queryWrapper));
|
||||||
|
|
||||||
// 只有 totalRow 小于 0 的时候才会去查询总量
|
|
||||||
// 这样方便用户做总数缓存,而非每次都要去查询总量
|
|
||||||
// 一般的分页场景中,只有第一页的时候有必要去查询总量,第二页以后是不需要的
|
|
||||||
if (page.getTotalRow() < 0) {
|
|
||||||
QueryWrapper countQueryWrapper = MapperUtil.optimizeCountQueryWrapper(queryWrapper);
|
|
||||||
long count = selectCountByQuery(schema, tableName, countQueryWrapper);
|
|
||||||
page.setTotalRow(count);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (page.isEmpty()) {
|
|
||||||
return page;
|
return page;
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
// 将之前设置的 limit 清除掉
|
||||||
|
// 保险起见把重置代码放到 finally 代码块中
|
||||||
|
CPI.setLimitRows(queryWrapper, null);
|
||||||
|
CPI.setLimitOffset(queryWrapper, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
//重置 selectColumns
|
|
||||||
CPI.setSelectColumns(queryWrapper, selectColumns);
|
|
||||||
//重置 orderBys
|
|
||||||
CPI.setOrderBys(queryWrapper, orderBys);
|
|
||||||
//重置 join
|
|
||||||
CPI.setJoins(queryWrapper, joins);
|
|
||||||
|
|
||||||
int offset = page.getPageSize() * (page.getPageNumber() - 1);
|
|
||||||
queryWrapper.limit(offset, page.getPageSize());
|
|
||||||
|
|
||||||
List<Row> records = selectListByQuery(schema, tableName, queryWrapper);
|
|
||||||
page.setRecords(records);
|
|
||||||
|
|
||||||
// 将之前设置的 limit 清除掉
|
|
||||||
CPI.setLimitRows(queryWrapper, null);
|
|
||||||
CPI.setLimitOffset(queryWrapper, null);
|
|
||||||
|
|
||||||
return page;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,7 +42,7 @@ public class MapperUtil {
|
|||||||
*
|
*
|
||||||
* <p><pre>
|
* <p><pre>
|
||||||
* {@code
|
* {@code
|
||||||
* SELECT COUNT(*) AS `total` FROM ( ...用户构建的 SQL 语句... );
|
* SELECT COUNT(*) AS `total` FROM ( ...用户构建的 SQL 语句... ) AS `t`;
|
||||||
* }
|
* }
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
@ -58,22 +58,25 @@ public class MapperUtil {
|
|||||||
* 优化 COUNT 查询语句。
|
* 优化 COUNT 查询语句。
|
||||||
*/
|
*/
|
||||||
public static QueryWrapper optimizeCountQueryWrapper(QueryWrapper queryWrapper) {
|
public static QueryWrapper optimizeCountQueryWrapper(QueryWrapper queryWrapper) {
|
||||||
List<QueryColumn> selectColumns = CPI.getSelectColumns(queryWrapper);
|
// 对克隆对象进行操作,不影响原来的 QueryWrapper 对象
|
||||||
List<QueryColumn> groupByColumns = CPI.getGroupByColumns(queryWrapper);
|
QueryWrapper clone = queryWrapper.clone();
|
||||||
|
// 将最后面的 order by 移除掉
|
||||||
|
CPI.setOrderBys(clone, null);
|
||||||
|
// 获取查询列和分组列,用于判断是否进行优化
|
||||||
|
List<QueryColumn> selectColumns = CPI.getSelectColumns(clone);
|
||||||
|
List<QueryColumn> groupByColumns = CPI.getGroupByColumns(clone);
|
||||||
// 如果有 distinct 语句或者 group by 语句则不优化
|
// 如果有 distinct 语句或者 group by 语句则不优化
|
||||||
// 这种一旦优化了就会造成 count 语句查询出来的值不对
|
// 这种一旦优化了就会造成 count 语句查询出来的值不对
|
||||||
if (hasDistinct(selectColumns) || hasGroupBy(groupByColumns)) {
|
if (hasDistinct(selectColumns) || hasGroupBy(groupByColumns)) {
|
||||||
return rawCountQueryWrapper(queryWrapper);
|
return rawCountQueryWrapper(clone);
|
||||||
}
|
}
|
||||||
// 判断能不能清除 join 语句
|
// 判断能不能清除 join 语句
|
||||||
if (canClearJoins(queryWrapper)) {
|
if (canClearJoins(clone)) {
|
||||||
CPI.setJoins(queryWrapper, null);
|
CPI.setJoins(clone, null);
|
||||||
}
|
}
|
||||||
// 最后将最后面的 order by 移除掉
|
// 将 select 里面的列换成 COUNT(*) AS `total`
|
||||||
// 将 select 里面的列换成 COUNT(*) AS `total` 就好了
|
CPI.setSelectColumns(clone, Collections.singletonList(count().as("total")));
|
||||||
CPI.setOrderBys(queryWrapper, null);
|
return clone;
|
||||||
CPI.setSelectColumns(queryWrapper, Collections.singletonList(count().as("total")));
|
|
||||||
return queryWrapper;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean hasDistinct(List<QueryColumn> selectColumns) {
|
private static boolean hasDistinct(List<QueryColumn> selectColumns) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user