MyBatis基础入门6:关联映射

关联映射的本质就是连表查询,用于多对一和一对多的表结构。

首先我们来新建两张表,student表和teacher表,在这里我们规定一个老师可以对应多个学生,而一个学生只能对应一个老师。

 

多对一查询

我们创建对应的实体类

 连表查询

<select id="selectStudentTeacher" resultMap="StudentTeacher">
        SELECT student.*,teacher.Tname from
        student left join teacher on teacher.id = student.t_id
    </select>
    <!-- resultMap:返回映射,要保证数据库字段和实体类字段的一致  -->
    <resultMap id="StudentTeacher" type="com.qcby.entity.Student">
        <!--     property:实体类当中的字段; column:数据库当中的字段  -->
        <result property="id" column="id"/>
        <result property="sName" column="Sname"/>
        <result property="sex" column="sex"/>
        <result property="age" column="age"/>
        <result property="t_id" column="t_id"/>

        <!--     association:复杂的属性要特殊处理 ;javaType:复杂属性的类型  -->
        <association property="teacher" javaType="com.qcby.entity.Teacher">
            <result property="id" column="id"/>
            <result property="tName" column="Tname"/>
        </association>
    </resultMap>

 

分步查询 

<!-- 分步查询 -->
    <!-- select * from student:首先查询一个表的全部信息-->
    <!-- select * from teacher where id = #{t_id} :然后根据两个表的关联字段查询另一个表的信息 -->
    <select id="StudentTeacher2" resultMap="StudentTeacher2">
        select * from student
    </select>
    <resultMap id="StudentTeacher2" type="com.qcby.entity.Student">
        <result property="id" column="id"/>
        <result property="sName" column="Sname"/>
        <result property="sex" column="sex"/>
        <result property="age" column="age"/>
        <result property="t_id" column="t_id"/>
        <!--     column="t_id"  :两个表的关联字段   -->
        <!--        select="teacher1" : 调用teacher1方法-->
        <association property="teacher" javaType="com.qcby.entity.Teacher" column="t_id" select="teacher1"/>
    </resultMap>
    <select id="teacher1" resultType="com.qcby.entity.Teacher">
        select * from teacher where id = #{t_id}
    </select>

 

 可以看到,虽然查询方式不同,但是查询结果相同。

一对多查询

我们需要修改两个实体类信息,因为是一对多,所以应该在老师类里添加学生集合

 

连表查询

<select id="getTeacherStudent" resultMap="teacherStudent">
        SELECT student.*,teacher.Tname from
        student left join teacher on teacher.id = student.t_id
    </select>
    <resultMap id="teacherStudent" type="com.qcby.entity.Teacher2">
        <result property="id" column="id"/>
        <result property="tName" column="Tname"/>
    <!--  复杂的属性我们需要单独去处理 collection:处理集合 ;association:处理对象-->
    <!--  ofType:在集合中的泛型类型      -->
        <collection property="student2s" ofType="com.qcby.entity.Student2">
            <result property="id" column="id"/>
            <result property="sName" column="Sname"/>
            <result property="sex" column="sex"/>
            <result property="age" column="age"/>
            <result property="t_id" column="t_id"/>
        </collection>
    </resultMap>

 分步查询

<!--分步查询 -->
    <!--select * from teacher  -->
    <!--select * from student where t_id = #{id}   -->
    <select id="getTeacherStudent2" resultMap="teacherStudent2">
        select * from teacher
    </select>
    <resultMap id="teacherStudent2" type="com.qcby.entity.Teacher2">
        <result property="id" column="id"/>
        <result property="tName" column="Tname"/>
        <collection property="student2s" ofType="com.qcby.entity.Student2" column="id" select="getStudent"/>
    </resultMap>
    <select id="getStudent" resultType="com.qcby.entity.Student2">
        select * from student where t_id = #{id}
    </select>
Teacher2{id=1, tName='张老师', student2s=[Student2{id=1, sName='张三', sex='男', age=18, t_id=1}, Student2{id=2, sName='李四', sex='女', age=18, t_id=1}, Student2{id=3, sName='王五', sex='男', age=18, t_id=1}, Student2{id=4, sName='小白', sex='女', age=18, t_id=1}, Student2{id=5, sName='小黑', sex='男', age=18, t_id=1}]}
Teacher2{id=2, tName='李老师', student2s=[Student2{id=6, sName='小红', sex='女', age=20, t_id=2}, Student2{id=7, sName='小李', sex='男', age=20, t_id=2}, Student2{id=8, sName='小张', sex='女', age=20, t_id=2}, Student2{id=9, sName='小赵', sex='男', age=20, t_id=2}, Student2{id=10, sName='小王', sex='女', age=20, t_id=2}]}

可以看到查询结果依然相同。

延迟加载策略

首先我们在主配置文件中设置延迟加载

<setting name="lazyLoadingEnabled" value="true"/>   //延迟加载的全域开关,开启时所有关联对象都会延迟加载。
<setting name="aggressiveLazyLoading" value="false"/> //当它开启时,任何方式的调用都会加载该对象的所有属性,否则就是按需加载。

我们上述所写分步查询是有缺陷的,为了初步理解分步查询,我们在查询老师(学生)时,将方法写到了学生(老师)的目标xml文件中。这么写在开发中是不合理的。

我们将分步查询的第二步写回到对应的文件中,这样各自查询时皆可调用该方法。

我们以一对多中查询老师主类为例,将分步查询第二步放回到StudentDao.xml文件中。注意放回时我们需要给方法加入参,这样StudentTset方法可以自己调用getStudent方法。

<select id="getStudent" resultType="com.qcby.entity.Student2" parameterType="java.lang.Integer">
        select * from student where t_id = #{id}
</select>

getStudent方法写回之后,collection处理学生集合时调用getStudent方法也需要修改:

<collection property="student2s" ofType="com.qcby.entity.Student2"
            column="id" select="com.qcby.dao.StudentDao.getStudent"
                 
 />

我们来测试一下

首先查询所有的teacher信息,这里包含student集合,所以该测试方法会进行两步查询。

public void getTeacherStudent2(){
        List<Teacher2> teachers = mapper.getTeacherStudent2();
        for (Teacher2 teacher : teachers) {
            System.out.println(teacher);
        }
    }

 接下来我们仅查询老师的名字,这里并不涉及到学生信息,请注意查询结果。

public void getTeacherStudent2(){
        List<Teacher2> teachers = mapper.getTeacherStudent2();
        for (Teacher2 teacher : teachers) {
            System.out.println(teacher.gettName());
        }
    }

我们对collection添加fetchType = "eager"  再来查询老师的名字,按照上述结果,这里不涉及学生信息,本应只执行一条查询语句。请注意查询结果。

<collection property="student2s" ofType="com.qcby.entity.Student2"
                    column="id" select="com.qcby.dao.StudentDao.getStudent"
                    fetchType="eager"
        />
public void getTeacherStudent2(){
        List<Teacher2> teachers = mapper.getTeacherStudent2();
        for (Teacher2 teacher : teachers) {
            System.out.println(teacher.gettName());
        }
    }

 我们可以看到,在打印出我们想要的结果之前,所有的查询语句都执行了,这是因为我们设置了fetchType属性,默认为fetchType = "lazy" 即延迟加载生效;当我们将其设定为eager时,延迟加载便失效了。

MyBatis基础入门1 - mac下MyBatis在idea的配置 

Mybatis基础入门2-----简单的增删改查 

MyBatis入门基础3 ---代理 

MyBatis基础入门4:#{}和${}传参的使用区别 

Mybatis基础入门5:动态sql

MyBatis基础入门7:注解开发 

MyBatis基础入门8:缓存机制 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值