1. 程式人生 > 其它 >淺析Mybatis一對多與PageHelper產生的問題

淺析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 加一對多的對映時,儘量選用“巢狀查詢”的方式。