8.多表查詢

MyBatis 實現多表查詢

  1. Mybatis 實現多表查詢方式
  • 業務裝配. 對__兩個表編寫單表查詢語句__,在業務(Service)把查詢的兩個結果進行關聯
  • 使用AutoMapping特性,在實現兩表聯合查詢時通過別名完成映射
  • 使用 MyBatis 的標籤進行實現
  1. 多表查詢時,類中包含另一個類的對象的分類
  • 單個對象
  • 集合對象

resultMap 標籤

  1. 標籤寫在mapper.xml中,由程序員控制SQL查詢結果與實體類的映射關係
  • 默認 MyBatis 使用 AutoMapping 特性(resultType)
  1. 使用標籤時,標籤不寫 resultType 屬性,而是使用 resultMap 屬性引用標籤

resultMap實現單表映射

使用 resultMap 實現單表映射關係(單從本例看不出什麼)
+ 數據庫設計:teacher(id,name)
+ 實體類設計(使用resultMap方式的話不要求屬性名和列名相同,但最好還是一樣)

public class Teacher{
    private int id1;
    private String name1;
}
  • mapper.xml 代碼
<resultMap type="teacher" id="mymap">
    <!-- 主鍵使用 id 標籤配置映射關係 --> 
    <id column="id" property="id1" />
    <!-- 其他列使用 result 標籤配置映射關係 --> 
    <result column="name" property="name1"/> 
</resultMap>

<select id="selAll" resultMap="mymap"> 
    select * from teacher 
</select>

resultMap關聯單個對象

使用 resultMap 實現關聯單個對象(N+1 方式)

  • N+1 查詢方式,先查詢出某個表的全部信息,根據這個表的信息查詢另一個表的信息
  • 與業務裝配的區別:
    • 在 service 裏面寫的代碼,由 mybatis 完成裝配
  • 實現步驟:
  1. 在 Student 實現類中包含了一個 Teacher 對象
public class Student { 
    private int id; 
    private String name; 
    private int age; 
    private int tid; 
    private Teacher teacher; // N+1
    ...
}
  1. 在 TeacherMapper 中提供一個查詢
<select id="selById" resultType="teacher" parameterType="int"> 
    select * from teacher where id=#{0} 
</select>
  1. 在 StudentMapper 中
    • 裝配一個對象時使用
    • property屬性: 對象在類中的屬性名
    • select屬性:通過哪個查詢查詢出這個對象的信息
    • column屬性: 把當前表的哪個列的值做爲參數傳遞給另一個查詢
    • 大前提:使用 N+1 方式時如果列名和屬性名相同可以不配置,使用 Automapping 特性.但是mybatis 默認只會給列專配一次
<resultMap type="student" id="stuMap"> 
    <id property="id" column="id"/> 
    <result property="name" column="name"/> 
    <result property="age" column="age"/> 
    <result property="tid" column="tid"/>
    <!-- 如果關聯一個對象 --> 
    <association 
                 property="teacher" 
                 select="com.buendia.mapper.TeacherMapper.selById" 
                 column="tid">
    </association>
</resultMap> 

<select id="selAll" resultMap="stuMap">
    select * from student 
</select>

把上面代碼簡化成

<resultMap type="student" id="stuMap"> 
    <!-- tid在下邊也引用到了,如果列和屬性名相同,可以省略,並且mybatis用automapping,但只會一次 -->
    <result column="tid" property="tid"/>
    <!-- 如果關聯一個對象 --> 
    <association 
                 property="teacher" 
                 select="com.buendia.mapper.TeacherMapper.selById" 
                 column="tid">
    </association> 
</resultMap> 
<select id="selAll" resultMap="stuMap"> 
    select * from student 
</select>

resultMap關聯單個對象(聯合查詢方式)

使用 resultMap 實現關聯單個對象(聯合查詢方式)

  • 只需要編寫一個 SQL,在 StudentMapper 中添加下面效果
  1. 只要__專配一個對象就用這個標籤__
  2. 此時把當做小的看待
  3. javaType 屬性:< association/>專配完後返回一個什麼類型的對象.取值是一個類(或類的別名)
<resultMap type="Student" id="stuMap1"> 
    <id column="sid" property="id"/> 
    <result column="sname" property="name"/> 
    <result column="age" property="age"/> 
    <result column="tid" property="tid"/> 
    <association property="teacher" javaType="Teacher" > 
        <id column="tid" property="id"/> 
        <result column="tname" property="name"/> 
    </association>
</resultMap> 

<select id="selAll1" resultMap="stuMap1"> 
    select s.id sid,s.name sname,age age,t.id tid,t.name tname 
    FROM student s left outer join teacher t on s.tid=t.id 
</select>

N+1 方式和聯合查詢方式對比

  • N+1:需求不確定時
  • 聯合查詢:需求中確定查詢時兩個表一定都查詢
  • N+1 名稱由來
  • 舉例:學生中有 3 條數據
  • 需求:查詢所有學生信息及授課老師信息
  • 需要執行的 SQL 命令
    1. 查詢全部學生信息:select * from 學生
    2. 執行 3 遍 select * from 老師 where id = 學生的外鍵
  • 使用多條 SQl 命令查詢兩表數據時,如果希望把需要的數據都查詢出來,需要執行 N+1 條 SQl 才能把所有數據庫查詢出來
  • 缺點:
    1. 效率低
  • 優點:
    1. 如果有的時候不需要查詢學生的同時查詢老師.只需要執行一個 select * from student;
  • 適用場景: 有的時候需要查詢學生同時查詢老師,有的時候只需要查詢學生
  • 如何解決 N+1 查詢帶來的效率低的問題
    1. 默認帶的前提: 每次都是兩個都查詢
    2. 使用兩表聯合查詢

resultMap關聯集合對象

  1. 在 Teacher 中添加 List
public class Teacher { 
    private int id; 
    private String name; 
    private List<Student> list;
    ...
}
  1. 在 StudentMapper.xml 中添加通過 tid 查詢
<select id="selByTid" parameterType="int" resultType="student"> 
    select * from student where tid=#{0} 
</select>
  1. 在 TeacherMapper.xml 中添加查詢全部
  • 當__屬性是集合類型時使用的標籤__
<resultMap type="teacher" id="mymap"> 
    <id column="id" property="id"/> 
    <result column="name" property="name"/> 
    <collection 
                property="list" 
                select="com.bjsxt.mapper.StudentMapper.selByTid" 
                column="id">
    </collection> 
</resultMap> 

<select id="selAll" resultMap="mymap"> 
    select * from teacher
</select>

resultMap實現加載集合數據(聯合查詢方式)

  1. 在 teacherMapper.xml 中添加
  • mybatis 可以通過主鍵判斷對象是否被加載過
  • 不需要擔心創建重複 Teacher
<resultMap type="teacher" id="mymap1"> 
    <id column="tid" property="id"/> 
    <result column="tname" property="name"/>
<collection property="students" ofType="student" > <!--property原來爲list,不對的話換下-->
    <id column="sid" property="id"/> 
    <result column="sname" property="name"/> 
    <result column="age" property="age"/> 
    <result column="tid" property="tid"/> 
    </collection> 
</resultMap> 

<select id="selAll1" resultMap="mymap1"> 
    select t.id tid,t.name tname,s.id sid,s.name sname,age,tid 
    from teacher t LEFT JOIN student s on t.id=s.tid; 
</select>

使用 AutoMapping 結合別名實現多表查詢

  • 只能使用多表聯合查詢方式
  • 要求:查詢出的列別名和屬性名相同
  • 實現方式
  1. 在 SQL 是關鍵字符,兩側添加反單引號
<select id="selAll" resultType="student">
select t.id `teacher.id`,t.name `teacher.name`,s.id id,s.name name,age,tid 
    from student s LEFT JOIN teacher t on t.id=s.tid 
</select>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章