解决Mybatis-Plus或PageHelper多表分页查询总条数不对问题

在Mybatis-Plus 3.4版本后,分页查询进行了优化,但当涉及多表关联查询时,可能出现查询总数不准确的问题。分析发现,由于优化使得总条数查询仅针对主表,导致与实际查询数据的表数量不一致。解决办法是在分页查询时关闭优化,通过设置`setOptimizeCountSql(false)`,确保两次查询的SQL一致,从而修复问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Mybatis-Plus版本3.4之后,对分页查询进行了优化

对于单表查询是没有问题的。而需要多表关联查询(自写sql)时,就会查询调用Mybatis-Plus的

.page(E page, Wrapper queryWrapper);

方法是就就会出现查询总数不对问题。

业务需要查询的数据

我这边业务比较复杂,是做项目的时候发现的问题,(本人比较懒)没有重新写demo。所以就不要太关注业务逻辑。只要知道符合条件的数据是69条。
在这里插入图片描述

分析

正常使用分页查询时的代码
在这里插入图片描述

运行的查询sql后台日志打印情况
在这里插入图片描述

可以看到Mybatis-Plus框架分页查询时,使用了两次查询,先查询总条数,再查询数据。而做了优化就是给第一个查询进行了优化(只查主表符合查询条件的总条数),这就导致两条查询sql的表数量不一致,从而导致查询总条数不一致的情况。搞清楚了原因,那就好解决了。

解决方式:关闭优化

代码调整(关闭分页查询优化)

Page<Object> toPage = (Page<Object>) pageQuery.toPage();
toPage.setOptimizeCountSql(false);

在这里插入图片描述
运行的查询sql后台日志打印情况
在这里插入图片描述
可以看到两次查询sql是一致的。解决问题。拜了个拜

### 关联条记录对分页功能的影响 当涉及一对关系时,如果从条记录对应同一个主记录,则可能导致分页结果异常。具体现为查询结果数量不准确重复数据过。这是因为标准的 SQL 分页语句(如 LIMIT 和 OFFSET)仅作用于最终的结果集,而不会考虑关联的数据分布情况[^2]。 对于这种情况,常见的影响包括: - **重复计数问题**:由于左连接(LEFT JOIN)的存在,每个条记录都会被计入数,从而导致记录数膨胀。 - **数据冗余**:同一主项可能会因个匹配的从项而在不同页面上次出现。 ```sql SELECT * FROM main_table m LEFT JOIN sub_table s ON m.id = s.main_id ORDER BY m.id LIMIT 10 OFFSET 0; ``` 上述代码展示了简单的一对查询方式,其中并未考虑到分页逻辑下的潜在问题[^5]。 ### 解决方案 为了应对这些问题,有几种可行的方法来改进分页机制: #### 方法一:使用子查询分离主次 通过先获取主所需的信息再基于这些信息去查找对应的从详情,这样可以有效避免重复计算的问题。此方法虽然增加了查询复杂度但是能更好地保持数据一致性并提高准确性[^4]。 ```sql WITH MainData AS ( SELECT id, name -- 主要字段 FROM main_table WHERE ... -- 过滤条件 GROUP BY id, name ORDER BY some_column LIMIT pageSize OFFSET (pageNo - 1) * pageSize ) SELECT md.*, st.detail_info FROM MainData md LEFT JOIN LATERAL ( SELECT detail_info FROM sub_table st WHERE st.main_id = md.id FETCH FIRST ROW ONLY ) st ON true; ``` 这段SQL利用了CTE(Common Table Expressions),首先过滤并限定了主中的记录范围,然后再逐一加载其关联的细节信息。注意这里用了LATERAL关键字配合子查询实现了一种类似于嵌套循环的方式,确保每次只取最新的那一条条特定的相关记录。 #### 方法二:采用聚合函数处理 另一种思路是在原始查询基础上加入GROUP BY子句,并结合COUNT()其他聚合操作统计每个主键下有少个相关实体存在,以此作为依据调整展示策略。这种方式适用于某些特殊场景,比如只需要知道某个父级对象拥有少个子节点而不必全部列出它们的情况。 ```sql SELECT m.*, COUNT(s.sub_id) as child_count FROM main_table m LEFT JOIN sub_table s ON m.id = s.main_id WHERE ... GROUP BY m.id, other_columns_of_main_table ORDER BY m.some_column LIMIT pageSize OFFSET (pageNo - 1) * pageSize; ``` 这种方法不仅解决了重复显示的问题,还额外提供了有关父子间联系强度的信息,有助于前端界面设计更加灵活样。 #### 方法三:借助全文搜索引擎优化深分页体验 在面对海量数据时,传统的数据库分页效率较低,尤其是在访问深层页面的时候现尤为明显。此时引入像Elasticsearch这样的分布式搜索平台能够显著改善用户体验。它支持复杂的DSL查询语言,允许开发者自定义评分算法以提升检索质量;更重要的是,ES内置了一些专门用于解决深度分页难题的技术手段,例如scroll API和search_after参数等[^3]。 ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你不懂、、、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值