2.1、提出需求
根据classId查询对应的班级信息,包括学生,老师
2.2、创建表和数据
在上面的一对一关联查询演示中,我们已经创建了班级表和教师表,因此这里再创建一张学生表
CREATETABLE student(
s_id INTPRIMARYKEY AUTO_INCREMENT,
s_name VARCHAR(20),
class_id INT
);
INSERTINTO student(s_name, class_id) VALUES('student_A', 1);
INSERTINTO student(s_name, class_id) VALUES('student_B', 1);
INSERTINTO student(s_name, class_id) VALUES('student_C', 1);
INSERTINTO student(s_name, class_id) VALUES('student_D', 2);
INSERTINTO student(s_name, class_id) VALUES('student_E', 2);
INSERTINTO student(s_name, class_id) VALUES('student_F', 2);
2.3、定义实体类
1、Student类
1package me.gacl.domain;
2 3/** 4 * @author gacl
5 * 定义student表所对应的实体类
6*/ 7publicclass Student {
8 9//定义属性,和student表中的字段对应10privateint id; //id===>s_id11private String name; //name===>s_name1213publicint getId() {
14return id;
15 }
1617publicvoid setId(int id) {
18this.id = id;
19 }
2021public String getName() {
22return name;
23 }
2425publicvoid setName(String name) {
26this.name = name;
27 }
2829 @Override
30public String toString() {
31return "Student [id=" + id + ", name=" + name + "]";
32 }
33 }
2、修改Classes类,添加一个List<Student> students属性,使用一个List<Student>集合属性表示班级拥有的学生,如下:
1package me.gacl.domain;
2 3import java.util.List;
4 5/** 6 * @author gacl
7 * 定义class表对应的实体类
8*/ 9publicclass Classes {
1011//定义实体类的属性,与class表中的字段对应12privateint id; //id===>c_id13private String name; //name===>c_name1415/**16 * class表中有一个teacher_id字段,所以在Classes类中定义一个teacher属性,
17 * 用于维护teacher和class之间的一对一关系,通过这个teacher属性就可以知道这个班级是由哪个老师负责的
18*/19private Teacher teacher;
20//使用一个List<Student>集合属性表示班级拥有的学生21private List<Student> students;
2223publicint getId() {
24return id;
25 }
2627publicvoid setId(int id) {
28this.id = id;
29 }
3031public String getName() {
32return name;
33 }
3435publicvoid setName(String name) {
36this.name = name;
37 }
3839public Teacher getTeacher() {
40return teacher;
41 }
4243publicvoid setTeacher(Teacher teacher) {
44this.teacher = teacher;
45 }
4647public List<Student> getStudents() {
48return students;
49 }
5051publicvoid setStudents(List<Student> students) {
52this.students = students;
53 }
5455 @Override
56public String toString() {
57return "Classes [id=" + id + ", name=" + name + ", teacher=" + teacher
58 + ", students=" + students + "]";
59 }
60 }
2.4、修改sql映射文件classMapper.xml
添加如下的SQL映射信息
1<!-- 2 根据classId查询对应的班级信息,包括学生,老师
3--> 4<!-- 5 方式一: 嵌套结果: 使用嵌套结果映射来处理重复的联合结果的子集
6 SELECT * FROM class c, teacher t,student s WHERE c.teacher_id=t.t_id AND c.C_id=s.class_id AND c.c_id=1
7--> 8<select id="getClass3" parameterType="int" resultMap="ClassResultMap3"> 9 select * from class c, teacher t,student s where c.teacher_id=t.t_id and c.C_id=s.class_id and c.c_id=#{id}
10</select>11<resultMap type="me.gacl.domain.Classes" id="ClassResultMap3">12<id property="id" column="c_id"/>13<result property="name" column="c_name"/>14<association property="teacher" column="teacher_id" javaType="me.gacl.domain.Teacher">15<id property="id" column="t_id"/>16<result property="name" column="t_name"/>17</association>18<!-- ofType指定students集合中的对象类型 -->19<collection property="students" ofType="me.gacl.domain.Student">20<id property="id" column="s_id"/>21<result property="name" column="s_name"/>22</collection>23</resultMap>2425<!--26 方式二:嵌套查询:通过执行另外一个SQL映射语句来返回预期的复杂类型
27 SELECT * FROM class WHERE c_id=1;
28 SELECT * FROM teacher WHERE t_id=1 //1 是上一个查询得到的teacher_id的值
29 SELECT * FROM student WHERE class_id=1 //1是第一个查询得到的c_id字段的值
30-->31<select id="getClass4" parameterType="int" resultMap="ClassResultMap4">32 select * from class where c_id=#{id}
33</select>34<resultMap type="me.gacl.domain.Classes" id="ClassResultMap4">35<id property="id" column="c_id"/>36<result property="name" column="c_name"/>37<association property="teacher" column="teacher_id" javaType="me.gacl.domain.Teacher" select="getTeacher2"></association>38<collection property="students" ofType="me.gacl.domain.Student" column="c_id" select="getStudent"></collection>39</resultMap>4041<select id="getTeacher2" parameterType="int" resultType="me.gacl.domain.Teacher">42 SELECT t_id id, t_name name FROM teacher WHERE t_id=#{id}
43</select>4445<select id="getStudent" parameterType="int" resultType="me.gacl.domain.Student">46 SELECT s_id id, s_name name FROM student WHERE class_id=#{id}
47</select>
2.5、编写单元测试代码
1package me.gacl.test;
2 3import me.gacl.domain.Classes;
4import me.gacl.util.MyBatisUtil;
5import org.apache.ibatis.session.SqlSession;
6import org.junit.Test;
7 8publicclass Test4 {
910 @Test
11publicvoid testGetClass3(){
12 SqlSession sqlSession = MyBatisUtil.getSqlSession();
13/**14 * 映射sql的标识字符串,
15 * me.gacl.mapping.classMapper是classMapper.xml文件中mapper标签的namespace属性的值,
16 * getClass3是select标签的id属性值,通过select标签的id属性值就可以找到要执行的SQL
17*/18 String statement = "me.gacl.mapping.classMapper.getClass3";//映射sql的标识字符串
19//执行查询操作,将查询结果自动封装成Classes对象返回20 Classes clazz = sqlSession.selectOne(statement,1);//查询class表中id为1的记录
21//使用SqlSession执行完SQL之后需要关闭SqlSession22 sqlSession.close();
23//打印结果:Classes [id=1, name=class_a, teacher=Teacher [id=1, name=teacher1], students=[Student [id=1, name=student_A], Student [id=2, name=student_B], Student [id=3, name=student_C]]]24 System.out.println(clazz);
25 }
2627 @Test
28publicvoid testGetClass4(){
29 SqlSession sqlSession = MyBatisUtil.getSqlSession();
30/**31 * 映射sql的标识字符串,
32 * me.gacl.mapping.classMapper是classMapper.xml文件中mapper标签的namespace属性的值,
33 * getClass4是select标签的id属性值,通过select标签的id属性值就可以找到要执行的SQL
34*/35 String statement = "me.gacl.mapping.classMapper.getClass4";//映射sql的标识字符串
36//执行查询操作,将查询结果自动封装成Classes对象返回37 Classes clazz = sqlSession.selectOne(statement,1);//查询class表中id为1的记录
38//使用SqlSession执行完SQL之后需要关闭SqlSession39 sqlSession.close();
40//打印结果:Classes [id=1, name=class_a, teacher=Teacher [id=1, name=teacher1], students=[Student [id=1, name=student_A], Student [id=2, name=student_B], Student [id=3, name=student_C]]]41 System.out.println(clazz);
42 }
43 }
2.6、MyBatis一对多关联查询总结
MyBatis中使用collection标签来解决一对多的关联查询,ofType属性指定集合中元素的对象类型。