- 多个学生,对应一个老师
- 对于学生而言,关联…多个学生,关联一个老师**【多对一】**
- 对于老师而言,集合…一个老师,有多个学生**【一对多】**
10.1、按照查询嵌套处理
现在有一个需求,建立多个学生和老师间的关系,我们进行查询所有学生信息,包括学生的老师信息。
Teacher Bean
@Data
public class Teacher {
private int id;
private String name;
}
Student Bean
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
private int id;
private String name;
//学生需要关联一个老师
private Teacher teacher;
}
TeacherMapper 接口
public interface TeacherMapper {
Teacher getOneTeacher(int id);
}
StudentMapper 接口
public interface StudentMapper {
//查询所有学生的信息,以及对应的老师
List<Student> getAllStudent();
}
TeacherMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.johngea.mapper.TeacherMapper">
<select id="getOneTeacher" resultType="Teacher">
select * from teacher where id = #{id}
</select>
</mapper>
StudentMapper.xml
在原来的项目中使用 resultMap
,对于单个属性,只需要添加一个 <result property="" column=""/>
,但此处,Student
类中有一个 Teacher
属性,而 Teacher
属性又包含多个属性,因此 result
在此处并不适用。
在
reslutMap
中,还有以下标签:
- association (关联)
- collection (集合)
前面我们说过,对于学生而言,关联…多个学生,关联一个老师**【多对一】**,因此,此处我们应该用到association(关联)
。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.johngea.mapper.StudentMapper">
<!--思路:
1.查询所有的学生
2.根据查询出来的学生的tid,寻找对应的老师
-->
<!--第1步-->
<select id="getAllStudent" resultMap="StudentsTeacher">
select * from student
</select>
<!--设定对应属性-->
<resultMap id="StudentsTeacher" type="Student">
<association property="teacher" column="tid" javaType="Teacher" select="getOneTeacher" />
</resultMap>
<!--第2步-->
<select id="getOneTeacher" resultType="Teacher">
select * from teacher where id = #{id}
</select>
</mapper>
在 association
标签中,和 result
标签一样,有 property和column
属性,前面在学 resultMap
时,我们说过 property
是对应 JavaBean 中的属性, column 则对应的是数据库中的字段,而在数据库中 student 表是通过 tid 字段去查询对应的 teacher 。因此,在association
中,property
对应的应该是 Student 类中的 teacher 属性,而 column
对应的是数据库中 student 表的 tid 字段。
select: 仅仅做完对应关系是不够的,我们在代码中分析过,查对应老师前还需要先查询所有学生,根据查到学生的tid在去查对应的老师,所以我们还要用到嵌套查询,将查询老师的操作包含在查询在所有学生中,而 association
中有 select
属性可以帮我们完成这一步。
javaType: 查询完成后,需要将查询结果封装为一个对象,因为property
中的teacher是一个对象,需要给该对象设置类型赋值,因此由javaType完成该操作。
Test
@Test
public void getAllStudent(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
List<Student> students = mapper.getAllStudent();
for (Student student : students) {
System.out.println(student);
}
sqlSession.close();
}
运行结果
Student(id=1, name=小明, teacher=Teacher(id=1, name=秦老师))
Student(id=2, name=小红, teacher=Teacher(id=1, name=秦老师))
Student(id=3, name=小张, teacher=Teacher(id=1, name=秦老师))
Student(id=4, name=小李, teacher=Teacher(id=1, name=秦老师))
Student(id=5, name=小王, teacher=Teacher(id=1, name=秦老师))
这种方式就类似于这样写 sql
语句:
select s.id,s.name,t.name from student s,teacher t where tid = (select id from teacher)
通过 sql
语句可以看出,这是一种嵌套子查询的方式。
10.2、按结果嵌套处理
StudentMapper.xml
<!--方式2.按照结果进行处理-->
<select id="getAllStudent2" resultMap="StudentsTeacher2">
select s.id sid,s.name sname,t.id tid,t.name tname from student s, teacher t where s.tid = t.id
</select>
<!--先对Student进行处理-->
<resultMap id="StudentsTeacher2" type="Student">
<!--id对应Student类中的id, sid对应sql语句中的sid-->
<result property="id" column="sid"/>
<!--name对应Student类中的name, sname对应sql语句中的name-->
<result property="name" column="sname"/>
<!--由于teacher在Student类中是一个属性, 而Teacher又有自己的属性, 我们需要再对Teacher进行单独处理,但是要将其设置为Teacher类型,因为其是属于Student类的属性-->
<association property="teacher" javaType="Teacher">
<!--这里的id对应Teacher类中的id, tid对应sql语句中的tid-->
<result property="id" column="tid"/>
<!--这里的name对应Teacher类中的name, tname对应sql语句中的tname-->
<result property="name" column="tname"/>
</association>
</resultMap>
进行测试,运行结果如下:
Student(id=1, name=小明, teacher=Teacher(id=1, name=秦老师))
Student(id=2, name=小红, teacher=Teacher(id=1, name=秦老师))
Student(id=3, name=小张, teacher=Teacher(id=1, name=秦老师))
Student(id=4, name=小李, teacher=Teacher(id=1, name=秦老师))
Student(id=5, name=小王, teacher=Teacher(id=1, name=秦老师))
这中方式就类似于这样写 sql
语句:
select s.id sid,s.name sname,t.id tid,t.name tname from student s, teacher t where s.tid = t.id
由 sql
语句可以看出,这是一种联表查询的方式。