目录
1、多对一处理
1.1、打个比方
1.2、实例环境搭建
1.3、目标:查询所有的学生信息以及对应的老师信息
方式一:查询嵌套
方式二:结果嵌套
2、一对多处理
2.1、目标:获取指定老师下的所有学生及老师的信息
方式一:结果嵌套
方式二:查询嵌套
3、小结
4、注意点
1、多对一处理
1.1、打个比方
image-20200726203354720
比如:多个学生对应一个老师
对于学生,关联,多个学生关联一个老师【多对一】
对于老师,集合,一个老师有多个学生【一对多】
1.2、实例环境搭建
搭建数据库表
CREATE TABLE teacher
(
id
INT(10) NOT NULL,
name
VARCHAR(30) DEFAULT NULL,
PRIMARY KEY (id
)
) ENGINE=INNODB DEFAULT CHARSET=utf8
INSERT INTO teacher(id
, name
) VALUES (1, ‘秦老师’);
CREATE TABLE student
(
id
INT(10) NOT NULL,
name
VARCHAR(30) DEFAULT NULL,
tid
INT(10) DEFAULT NULL,
PRIMARY KEY (id
),
KEY fktid
(tid
),
CONSTRAINT fktid
FOREIGN KEY (tid
) REFERENCES teacher
(id
)
) ENGINE=INNODB DEFAULT CHARSET=utf8
INSERT INTO student
(id
, name
, tid
) VALUES (‘1’, ‘小明’, ‘1’);
INSERT INTO student
(id
, name
, tid
) VALUES (‘2’, ‘小红’, ‘1’);
INSERT INTO student
(id
, name
, tid
) VALUES (‘3’, ‘小张’, ‘1’);
INSERT INTO student
(id
, name
, tid
) VALUES (‘4’, ‘小李’, ‘1’);
INSERT INTO student
(id
, name
, tid
) VALUES (‘5’, ‘小王’, ‘1’);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
我们画出两个表对应的关系,从学生这边看,是多对一的关系,student表的tid是外键,对应teacher表的id
image-20200726204610911
导入lombok依赖,下载lombok插件
org.projectlombok
lombok
1.18.12
provided
1
2
3
4
5
6
新建实体类Student和Teacher
学生的第三个字段tid对应一个老师,所以学生的实体类Student中第三个属性为Teacher类型
package pojo;
@data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private int id;
private String name;
//每个学生需要关联一个老师
private Teacher teacher;
}
1
2
3
4
5
6
7
8
9
10
11
package pojo;
@data
@AllArgsConstructor
@NoArgsConstructor
public class Teacher {
private int id;
private String name;
}
1
2
3
4
5
6
7
8
9
创建StudentMapper和TeacherMapper接口
package mapper;
public interface StudentMapper {
}
1
2
3
4
5
package mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import pojo.Teacher;
public interface TeacherMapper {
}
1
2
3
4
5
6
7
8
9
创建StudentMapper.xml和Teacher.xml文件
}
1
2
3
1.3、目标:查询所有的学生信息以及对应的老师信息
方式一:查询嵌套
在StudentMapper接口中添加getStudent方法,用来查询所有学生
public List getStudent();
1
StudentMapper.xml进行配置
首先用 getStudent方法 查询所有的学生信息
再利用resultMap进行查询嵌套映射
Student实体类中的id属性 ==> 数据库student表中的id字段
Student实体类中的name属性 ==> 数据库student表中的name字段
Student实体类中的teacher属性 ==> 数据库student表中的tid字段
利用select标签实现嵌套查询,绑定id为getStudent的查询语句,根据查询出来的学生的tid,寻找对应的老师!
@Test
public void getStudent() {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
List students = mapper.getStudent();
for (Student student : students) {
System.out.println(student);
}
sqlSession.close();
}
1
2
3
4
5
6
7
8
9
10
方式二:结果嵌套
StudentMapper.xml进行配置
首先用 getStudent2方法 条件查询
查询学生的id,别名sid
查询学生的name,别名sname
查询老师的name,别名tname
条件为 学生的tid=老师的id
利用resultMap进行结果嵌套映射
Student实体类中的id属性(sid) ==> 数据库student表中的id字段
Student实体类中的name属性(sname) ==> 数据student库表中的name字段
Student实体类中的teacher属性嵌套映射,由于是一个Teacher对象,使用association标签,且利用javaType指定java类型为Teacher
对该Teacher对象再次进行映射
Teacher实体类中的name属性(tname) ==> 数据库teacher表中的name字段
select s.id sid,s.name sname,t.name tname
from student s,teacher t
where s.tid=t.id
1
2
3
4
5
6
7
8
9
10
11
12
测试类中添加测试方法
@Test
public void getStudent() {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
List students = mapper.getStudent();
for (Student student : students) {
System.out.println(student);
}
sqlSession.close();
}
1
2
3
4
5
6
7
8
9
10
2、一对多处理
对于老师,集合,一个老师有多个学生【一对多】
同上搭建环境,不同之处:
实体类
老师的第二个字段id对应多个学生,所以老师的实体类Teacher中第二个属性为Student的集合
package pojo;
@data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private int id;
private String name;
private int tid;
}
1
2
3
4
5
6
7
8
9
10
package pojo;
@data
@AllArgsConstructor
@NoArgsConstructor
public class Teacher {
private int id;
private String name;
//一个老师有多个学生
private List students;
}
1
2
3
4
5
6
7
8
9
10
11
2.1、目标:获取指定老师下的所有学生及老师的信息
方式一:结果嵌套
在TeacherMapper接口中添加getTeacher方法,用来获取指定老师下的所有学生及老师的信息
//获取指定老师下的所有学生及老师的信息
Teacher getTeacher(@Param(“tid”) int id);
1
2
TeacherMapper.xml进行配置
首先用 getTeacer方法 根据指定的老师id条件查询
查询学生的id,别名sid
查询学生的name,别名sname
查询老师的name,别名tname
查询老师的id,别名tid
条件为 学生的tid=老师的id
利用resultMap进行结果嵌套映射
Teacher实体类中的id属性(tid) ==> 数据库teacher表中的id字段
Teacher实体类中的name属性(tname) ==> 数据库teacher表中的name字段
Teacher实体类中的student集合属性嵌套映射,由于是Student集合,所以使用collection标签,并且利用oftype指定集合的泛型类型
对该Student集合再进行映射
Student实体类中的id属性(sid) ==> 数据库student表中的id字段
Student实体类中的name属性(sname) ==> 数据student库表中的name字段
Student实体类中的tid属性 ==> 数据student库表中的tid字段
<select id="getTeacher" resultMap="teacherStudent">
select s.id sid,s.name sname,t.name tname,t.id tid
from student s,teacher t
where s.tid=t.id and t.id=#{tid}
</select>
<resultMap id="teacherStudent" type="pojo.Teacher">
<result column="tid" property="id"/>
<result column="tname" property="name"/>
<!--
javaType:指定属性的类型
集合中的泛型信息,用oftype获取
-->
<collection property="students" ofType="pojo.Student">
<result column="sid" property="id"/>
<result column="sname" property="name"/>
<result column="tid" property="tid"/>
</collection>
</resultMap>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
测试类中添加测试方法
@Test
public void getStudent() {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
List students = mapper.getStudent();
for (Student student : students) {
System.out.println(student);
}
sqlSession.close();
}
1
2
3
4
5
6
7
8
9
10
得到结果
image-20200727162310840
方式二:查询嵌套
TeacherMapper.xml进行配置
首先用 getTeacher2方法 查询所有的老师信息
利用resultMap进行查询嵌套映射
Teacher实体类中的id属性 ==> 数据库teacher表中的id字段
Teacher实体类中的name属性 ==> 数据库teacher表中的name字段
Teacher实体类中的student集合属性 ==> 数据库teacher表中的id字段
利用select标签实现嵌套查询,绑定id为getStudentByTeacherID的查询语句,根据查询出来的老师的id,寻找对应的学生!
select * from teacher
@Test
public void getTeacher2() {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
Teacher teacher2 = mapper.getTeacher2(1);
System.out.println(teacher2);
sqlSession.close();
}
1
2
3
4
5
6
7
8
3、小结
关联association 【多对一】
集合collection 【一对多】
javaType 和 ofType
javaType用来指定实体类中属性的类型
ofType用来指定映射到集合中的pojo类型,泛型的约束类型
4、注意点
保证SQL的可读性,尽量保证通俗易懂
注意一对多和多对一中,属性和字段的问题
问题不好排查的情况下,建议使用日志排错