淺析Mybatis一對多與PageHelper產生的問題
阿新 • • 發佈:2021-06-14
一、問題記錄
在 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 加一對多的對映時,儘量選用“巢狀查詢”的方式。