SSM架構下,mapper.xml 中 association 标簽和 collection标簽的使用
當資料庫中表與表之間有關聯時,在對資料庫進行操作時,就不隻是針對某一張表了,需要聯表查詢
MyBatis中如何實作聯表查詢
1、首先建立兩張表
學生表(student)
ID:stu_id
姓名:stu_name
年齡:stu_age
性别:stu_gender
所在班級:g_id
班級表(grade)
ID:g_id
班級名稱:g_name
學生表和班級表通過 g_id進行關聯,一個班級對應多個學生
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5yMiJGM4cjZyMTN4UTO0UjNiFTY3EWM4YzMwMjNwkjN18CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
2、建立相應的實體類和mapper接口
(1)建立 Student類和 Grade 類(包名:com.bwlu.bean)
(2)建立 StudentMapper 接口和 GradeMapper 接口和相應的 XML 檔案(使用逆向生成可直接生成)
StudentMapper.java 接口
Student selectByPrimaryKey(Integer stuId);//按主鍵查詢一條記錄
StudentMapper.xml
select stu_id, stu_name, stu_age, stu_gender, g_id from student
where stu_id = #{stuId,jdbcType=INTEGER}
GradeMapper.java
Grade selectByPrimaryKey(Integer gId);//按主鍵查詢一條記錄
GradeMapper.xml
select g_id, g_name from grade
where g_id = #{gId,jdbcType=INTEGER}
3、在sql映射檔案中寫映射sql語句【聯合查詢:級聯屬性封裝結果集】
3.1第一種
(1)在 Student.java 中将 g_id 屬性換成班級類型(Grade),并添加相應的getter和setter方法
//private Integer g_id;
privateGrade grade;publicGrade getGrade() {returngrade;
}public voidsetGrade(Grade grade) {this.grade =grade;
}
(2)在 xml 中封裝結果集,并編寫相應的 sql 語句
select stu_id, stu_name, stu_age, stu_gender, g.g_id, g_name
from student s,grade g
where s.g_id = g.g_id AND stu_id = #{stuId,jdbcType=INTEGER}
(3)測試
@AutowiredprivateStudentMapper studentMapper;
@Testpublic voidtestAssociation() {
Student student= studentMapper.selectByPrimaryKey(6);
System.out.println(student);//Student [stuId=6, stuName=lixiang, stuAge=22, stuGender=1, grade=Grade [gId=3, gName=軟體(3)班]]
}
3.2第二種
(1)在 Student.java 中将 g_id 屬性換成班級類型(Grade),并添加相應的getter和setter方法,同 3.1 的(1)
(2)使用association來定義關聯對象的規則【比較正規的,推薦的方式】
select stu_id, stu_name, stu_age, stu_gender, g.g_id, g_name
from student s,grade g
where s.g_id = g.g_id AND stu_id = #{stuId,jdbcType=INTEGER}
(3)測試(同 3.1的(3),結果也一樣)
3.3第三種
(1)在 Student.java 中将 g_id 屬性換成班級類型(Grade),并添加相應的getter和setter方法,同 3.1 的(1)
(2)使用Association進行分步查詢【上述結果相當于使用嵌套結果集的形式】
select g_id, g_name from grade
where g_id = #{gId,jdbcType=INTEGER}
select stu_id, stu_name, stu_age, stu_gender, g_id
from student
where stu_id = #{stuId,jdbcType=INTEGER}
注:使用 resultType 傳回值類型進行接收,必須使用駝峰式命名,使資料庫中的字段和實體類中的字段對應。
(3)測試(同 3.1的(3),結果也一樣)
(2)中也可以指定為GradeMapper 下的方法。
懶加載機制【按需加載,也叫懶加載】
在 3.3 分步查詢中,每次查詢 Student對象的時候,都将關聯 Grade 的對象查詢出來了。
使用延遲加載,可以在需要 班級 資訊的時候,再去查詢,不需要的時候就不用查詢。
在 MyBatis 的全局配置檔案中,加入兩個配置
這樣,當我們查詢 Student對象的時候,
如果隻輸出學生姓名,就不會執行查詢班級資訊的 sql 語句(隻執行一條 sql 語句),
select stu_id, stu_name, stu_age, stu_gender, g_id from student where stu_id = ? Parameters: 6(Integer)
當需要班級資訊的時候才會執行,(執行兩條 sql 語句)
select stu_id, stu_name, stu_age, stu_gender, g_id from student where stu_id = ? Parameters: 6(Integer)
select g_id, g_name from grade where g_id = ? Parameters: 3(Integer)
3.4 上述是在多端(學生)查詢一端(班級)的資訊,用 association,當我們在一端查詢多端資訊的時候,需要使用 collection,查出的是一個集合
(1)在班級類(Grade)類中添加一個屬性List stuList,并添加相應的 getter 和 setter 方法
private ListstuList;public ListgetStuList() {returnstuList;
}public void setStuList(ListstuList) {this.stuList =stuList;
}
(2)使用collection标簽定義關聯的集合類型元素的封裝規則【collection:嵌套結果集的方式】
select g.g_id, g_name, stu_id, stu_name, stu_age, stu_gender
from grade g,student s
where g.g_id = s.g_id AND g.g_id = #{gId,jdbcType=INTEGER}
(3)測試
@AutowiredprivateGradeMapper gradeMapper;
@Testpublic voidtestCollection() {
Grade grade= gradeMapper.selectByPrimaryKey(3);
List stuList =grade.getStuList();for(Student stu:stuList){
System.out.println(stu);//Student [stuId=3, stuName=fenghen, stuAge=12, stuGender=1, grade=null]//Student [stuId=6, stuName=lixiang, stuAge=22, stuGender=1, grade=null]
}
}
注意:grade為null,因為 Student和 Grade互相嵌套,如果用 resultMap進行接收的話,會互相嵌套,最終導緻棧溢出,應用 resultType 進行接收,嵌套的類型為 null 值。
3.5 使用分步查詢結果集的方式
(1)在班級類(Grade)類中添加一個屬性List stuList,并添加相應的 getter 和 setter 方法,同 3.4 中的(1)
(2)在 GradeMapper.xml 中添加如下方法
select g_id, g_name from grade
where g_id = #{gId,jdbcType=INTEGER}
在 StudentMapper.xml 中添加如下方法 selectByGId :根據 g_id 查詢學生集合
select
stu_id, stu_name, stu_age, stu_gender,g_id
from student
where g_id = #{gId,jdbcType=INTEGER}
(3)測試(同 3.4的(3),結果也一樣)