通常我们可以直接用 select
标签进行查询并将对应列内容映射到对象中的属性。但如果对象中的属性存在诸如 List<Student>
的集合数据结构呢?也就是多对一查询。
例如:
@Data
public class Teacher {
private int tid;
private String name;
private List<Student> teachStudent;
public static void main(String[] args) {
try ( SqlSession sqlSession= MybatisUtil.getSqlSession(false)) {
TestMapper testMapper = sqlSession.getMapper(TestMapper.class);
Teacher teacher = testMapper.getTeacherById(1);
System.out.println(teacher);
}
}
}
在库中一个老师可以对应多个学生,在SQL语言中可以采用多表联查,联查的结果也是这一个老师对应N个学生的N条记录:
<select id="getTeacherById" resultMap="getTeacherById">
select * from student inner join teach on teach.Sno = Student.Sno inner join teacher on teacher.Tid = teach.Tid and teacher.Tid = #{tid}
</select>
<resultMap id="getTeacherById" type="Teacher">
<id column="Tid" property="tid"/>
<result column="Tname" property="name"/>
<collection property="teachStudent" ofType = "Student">
<id column="Sno" property="sno"/>
<result column="Sname" property="name"/>
<result column="Sage" property="age"/>
</collection>
</resultMap>
其中id
标签用于在多条记录中辨别是否为同一个对象的数据,比如上面的查询语句得到的结果中,tid
这一行始终为1
,因此所有的记录都应该是tid=1
的教师的数据,而不应该变为多个教师的数据,如果不加id进行约束,那么会被识别成多个教师的数据!这里学生集合也有一个 id,实际上和result效果一样。
除了一对多查询,有时候也会用到多对一查询。例如学生类:
@Data
public class Student {
private int sno;
private String name;
private int age;
private Teacher teacher;
}
我们希望每查询到一个学生对象就再加上他的老师信息:
<select id ="selectStudentWithTeacher" resultMap="selectStudentWithTeacher">
select * from student left join teach on teach.Sno = Student.Sno left join teacher on teacher.Tid = teach.Tid
</select>
<resultMap id="selectStudentWithTeacher" type="Student">
<id column="Sno" property="sno"/>
<result column="Sname" property="name"/>
<result column="Sage" property="age"/>
<association property="teacher" javaType="Teacher">
<id column="Tid" property="tid"/>
<result column="Tname" property="name"/>
</association>
</resultMap>