浅析Mybatis一对多与PageHelper产生的问题
一、问题记录
在 mybatis 中使用 collection 映射一对多关系的结果集时,会存在2个问题:
1、问题一:total总数与实际返回数量不一致
2、问题二:实际返回数据有问题
二、Mybatis一对多的两种mapper写法
Mybatis提供了两种一对多的解决方案:一种是嵌套结果,一种是嵌套查询
1、嵌套结果查询:
多表关联查询出一对一的关系,再封装成Teacher对象
<select id="getTeacher" resultMap="TeacherMap">
select t.id id, t.name tname, s.id sid, s.name sname, s.tid tid
from teacher t
left join student s
on t.id = s.tid
</select>
<resultMap type="Teacher" id="TeacherMap">
<result property="id" column="id"/>
<result property="name" column="tname"/>
<collection property="students" ofType="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<result property="tid" column="tid"/>
</collection>
</resultMap>
2、嵌套查询
先查出Teacher对象,再遍历匹配出相应的Student对象集合
<select id="xxx" resultMap="TeacherMap">
select id, name from teacher
</select>
<select id="selectStudents" resultType="Student">
select id, tid, name from student
</select>
<resultMap type="Teacher" id="TeacherMap">
<result property="id" column="id"/>
<result property="name" column="name"/>
<collection property="students" ofType="Student" select="selectStudents"column="id" javaType="java.util.List">
<result property="id" column="id"/>
<result property="tid" column="tid"/>
<result property="name" column="name"/>
</collection>
</resultMap>
三、问题剖析
1、方法一采用关联查询的方式查询数据。
select t.id id, t.name tname, s.id sid, s.name sname, s.tid tid
from teacher t
left join student s
on t.id = s.tid
查询结果如下4条
如果使用PageHelper,会在以上sql种拼接limit,这样产生的影响是:
(1)对 total 的影响
因为老师只有2个,我们需要的返回total是2,但是由于多表关联查出来的是以上结果,那么total就会返回4,导致total错误
,进而导致页面分页也有问题
(2)对返回结果的影响
- 如果pagesize >= 4,那所有结果均返回,并且会生成Teacher对象,返回两条结果。
没问题
- 如果pagesize < 4, 比如是2,那李老师就被limit掉了,返回结果只有张老师一个人。
有问题
问题原因:因为 teacher 和 student 表是一对多的关系,所以在关联查询时,虽然是查出来了 4 条记录,但是这 4 条记录中,teacher 有重复的(因为一个 teacher 有多个学生)。而这些记录在封装成 Student 对象返回前端时,会按 Student 进行逐个封装,这样就会出现数量减少的情况。
2、方法二首先执行了如下sql
select id, name from teacher
查询结果2条
如果使用PageHelper,会在以上sql种拼接limit
(1)关于 total
由于pageHelper只会对紧接着的第一个sql起作用,因此total返回2,没问题
(2)关于返回结果
PageHelper不会影响后面的sql,因此,不影响结果。没问题
所以在使用 pageHelper 加一对多的映射时,尽量选用“嵌套查询”的方式。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
2017-06-14 浅析nginx的server及server_name的意义详解
2017-06-14 浅析JS对象中的排序属性和常规属性、对象内属性、快属性和慢属性