关于 MyBatis-Plus 分页 中count优化导致最终的总数量不正确的问题

885 阅读1分钟

MyBatis-Plus 在使用Page进行分页查询的时候,会生成查询数量的sql,但是在生成sql的时候会对原sql进行优化,

JsqlParserCountOptimize

1.添加包含groupBy 不去除orderBy

if (null == groupBy && CollectionUtils.isNotEmpty(orderBy)) {  
    plainSelect.setOrderByElements(null);  
    sqlInfo.setOrderBy(false);  
}

2.selectItems contains #{} ${}, which will be translated to ?, and it may be in a function: power(#{myInt},2)

for (SelectItem item : plainSelect.getSelectItems()) {  
    if (item.toString().contains(StringPool.QUESTION_MARK)) {  
        return sqlInfo.setSql(SqlParserUtils.getOriginalCountSql(selectStatement.toString()));  
    }  
}

3.包含 distinct、groupBy不优化

if (distinct != null || null != groupBy) {  
    return sqlInfo.setSql(SqlParserUtils.getOriginalCountSql(selectStatement.toString()));  
}

4.包含 join 连表,进行判断是否移除 join 连表

            if (optimizeJoin && CollectionUtils.isNotEmpty(joins)) {
                boolean canRemoveJoin = true;
                String whereS = Optional.ofNullable(plainSelect.getWhere()).map(Expression::toString).orElse(StringPool.EMPTY);
                for (Join join : joins) {
                    if (!join.isLeft()) {
                        canRemoveJoin = false;
                        break;
                    }
                    Table table = (Table) join.getRightItem();
                    String str = Optional.ofNullable(table.getAlias()).map(Alias::getName).orElse(table.getName()) + StringPool.DOT;
                    String onExpressionS = join.getOnExpression().toString();
                    /* 如果 join 里包含 ?(代表有入参) 或者 where 条件里包含使用 join 的表的字段作条件,就不移除 join */
                    if (onExpressionS.contains(StringPool.QUESTION_MARK) || whereS.contains(str)) {
                        canRemoveJoin = false;
                        break;
                    }
                }
                if (canRemoveJoin) {
                    plainSelect.setJoins(null);
                }
            }

5.优化 SQL

    plainSelect.setSelectItems(COUNT_SELECT_ITEM);

COUNT_SELECT_ITEM 这里就是count(1)

会出现的问题

就是对于上边的第4点,如果 join 里不包含 ?(代表有入参) 或者 where 条件里不包含使用 join 的表的字段作条件 就是把 join表给优化掉,如果主表和关联表是一对多的关系,那么最后查询出来的count是主表的总数据,就不对了

解决方法

将sql 的count优化关掉

page.setOptimizeCountSql(false);