复杂查询(一对多,多对一)

在之前的结果集映射中我们曾说,如果世界总是这么简单就好了。

现在,我们接触到了世界不简单的一面了....

举例:一个老师和一群学生

对于学生而言:多个学生,对应一个学生,所以是【多对一】的关系,也就是关联

对于老师而言:一个老师,对应多个学生,所以是【一对多】的关系,也就是集合

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的属性,虽然连表查询能查出来,但是却无法映射上去,为了解决这一问题,有如下两种方法。

按照查询嵌套处理

具体思路:

  1. 先查询Student全部信息:id,name,tid
  2. 因为数据库与pojo不能直接映射,所有需要结果集映射。
  3. 在结果集映射中,前面两个都能映射上去,但是最后一个在pojo里是一种类型,我们需要再进行一些操作
  4. 在此运用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>

按照结果嵌套处理

具体思路:

  1. 这回我们直接按照这个sql语句来搞
  2. 查询出来的东西本质上还是一个sutdent,这回的三个对象:sid,sname,tname
  3. 相比较上一种查询一个Student之后再查询出一个Teacher,这次是只查询一个Student然后绑定上从Teacher里查到的Tname
  4. 首先绑定id和name,然后再用association
  5. 在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>

总结:

  1. association:【关联】关联到某个对象
  2. collection:【集合】包含了某个集合
  3. javaType&ofType:javaTupe代表的是一个确切的类型,但是Teacher中的属性是一个list集合,所以我们需要遍历里面的类型,这里用ofType进行包装

面试高频:

  • Mysql引擎
  • innoDB底层原理
  • 索引
  • 索引优化


醉后不知天在水,满船清梦压星河