复杂查询(一对多,多对一)
在之前的结果集映射中我们曾说,如果世界总是这么简单就好了。
现在,我们接触到了世界不简单的一面了....
举例:一个老师和一群学生
对于学生而言:多个学生,对应一个学生,所以是【多对一】的关系,也就是关联
对于老师而言:一个老师,对应多个学生,所以是【一对多】的关系,也就是集合
1.多对一
实体:
public class Student {
private int id;
private String name;
//学生需要关联一个老师
//不要用tid关联
private Teacher teacher;
}
public class Teacher {
private int id;
private String name;
}
在select标签中进行的多表查询,却没有办法映射给实体类中的类,比如学生类中一个类型为Teacher的属性,虽然连表查询能查出来,但是却无法映射上去,为了解决这一问题,有如下两种方法。
按照查询嵌套处理
具体思路:
- 先查询Student全部信息:id,name,tid
- 因为数据库与pojo不能直接映射,所有需要结果集映射。
- 在结果集映射中,前面两个都能映射上去,但是最后一个在pojo里是一种类型,我们需要再进行一些操作
- 在此运用association标签,首先确定关联的pojo属性(teacher),在去找数据库对应的字段(tid),在此进行一个嵌套查询(根据tid进行select)得到一个新的表,最后用javaType确定这个新集合封装的类型(Teacher),到此,大功告成
注意:property的teacher不是类型Teacher的别名优化,他是student的属性名字,如果你把student的teacher属性名字改为teacher2,在这里一样需要对应起来
<select id="getStuednt" resultMap="StudentTeacher">
select * from mybatis.student;
</select>
<resultMap id="StudentTeacher" type="Student">
<result property="id" column="id"/>
<result property="name" column="name"/>
<association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
</resultMap>
<select id="getTeacher" resultType="Teacher">
select * from mybatis.teacher where id=#{tid};
</select>
按照结果嵌套处理
具体思路:
- 这回我们直接按照这个sql语句来搞
- 查询出来的东西本质上还是一个sutdent,这回的三个对象:sid,sname,tname
- 相比较上一种查询一个Student之后再查询出一个Teacher,这次是只查询一个Student然后绑定上从Teacher里查到的Tname
- 首先绑定id和name,然后再用association
- 在association里再进行一次result映射,这回是将集合中的tname映射给这个student中teacher对象的属性
<!--按照结果嵌套查询-->
<select id="getStudent2" resultMap="StudentTeacher2">
select s.id sid,s.name sname,t.name tname
from student s,teacher t
where s.tid = t.id
</select>
<resultMap id="StudentTeacher2" type="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<association property="teacher" javaType="Teacher">
<result property="name" column="tname"/>
</association>
</resultMap>
2.一对多
比如一个老师有多个学生!
对于老师而言,就是一对多
实体:
public class Student {
private int id;
private String name;
private int tid;
}
public class Teacher {
private int id;
private String name;
//一个老师拥有多个学生
private List<Student> students;
}
按照结果嵌套处理
注意这里,javaTupe代表的是一个确切的类型,但是Teacher中的属性是一个list集合,所以我们需要遍历里面的类型,这里用ofType进行包装,这里javaType可以省略
<!--按结果嵌套查询-->
<select id="getTeacher" resultMap="TeacherStudent">
select t.id tid,t.name tname,s.id sid,s.name sname
from student s,teacher t
where s.tid = t.id and t.id = #{tid}
</select>
<resultMap id="TeacherStudent" type="Teacher">
<result property="id" column="tid"/>
<result property="name" column="tname"/>
<!--注意这里,javaTupe代表的是一个确切的类型,但是Teacher中的属性是一个list集合,所以我们需要遍历里面的类型,这里用ofType进行包装,这里javaType可以省略-->
<collection property="students" javaType="ArrayList" ofType="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<result property="tid" column="tid"/>
</collection>
</resultMap>
按照查询嵌套处理
注意此处。本来我们是不需要id映射的,因为数据库和实体类名字都相同,但是这里再collection标签处我们使用了id,将其作为值传递给了下面的getStudentByTeacherId
所以查出来的id是没有被映射的,需要我们手动加一下
另外以后如果有这种情况最好还是全部映射一下,也不是太麻烦,字段多的情况再另说
collection会抢占自动映射
<select id="getTeacher2" resultMap="TeacherStudent2">
select * from mybatis.teacher where id = #{tid};
</select>
<resultMap id="TeacherStudent2" type="Teacher">
<!--注意此处。本来我们是不需要id映射的,因为数据库和实体类名字都相同,但是这里再collection标签处我们使用了id,将其作为值传递给了下面的getStudentByTeacherId
所以查出来的id是没有被映射的,需要我们手动加一下
另外以后如果有这种情况最好还是全部映射一下,也不是太麻烦,字段多的情况再另说
collection会抢占自动映射
-->
<result property="id" column="id"/>
<collection property="students" column="id" javaType="ArrayList" ofType="Student" select="getStudentByTeacherId"/>
</resultMap>
<select id="getStudentByTeacherId" resultType="Student">
select * from mybatis.student where tid = #{tid};
</select>
总结:
- association:【关联】关联到某个对象
- collection:【集合】包含了某个集合
- javaType&ofType:javaTupe代表的是一个确切的类型,但是Teacher中的属性是一个list集合,所以我们需要遍历里面的类型,这里用ofType进行包装
面试高频:
- Mysql引擎
- innoDB底层原理
- 索引
- 索引优化
Comments | NOTHING