mybatis之高级映射(多对一)三种方式

一、第一种方式(一条SQL语句):级联属性映射

 【CarMapper.xml样例】:

<resultMap id="studentResultMap" type="Student">
        <!--多对一映射的第一种方式:一条SQL语句,级联属性映射。colum的值赋给property的值-->
        <id property="sid" column="sid"/>
        <result property="sname" column="sname"/>
        <result property="clazz.cid" column="cid"/>
        <result property="clazz.cname" column="cname"/>
    </resultMap>
<select id="selectById" resultMap="studentResultMap">
    select
        s.sid,s.sname,c.cid,c.cname
    from
        t_student s left join t_clazz c on s.cid=c.cid
    where
        s.sid=#{sid}
</select>

【测试样例】:

@Test
    public void testSelectById(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        Student student = mapper.selectById(1);
        System.out.println(student.getSname());
        System.out.println(student.getClazz().getCid());
        System.out.println(student.getClazz().getCname());
        sqlSession.close();

    }

二、第二种方式(一条SQL语句):association标签

【CarMapper.xml样例】:

<resultMap id="studentResultMapAssociation" type="Student">
        <id property="sid" column="sid"/>
        <result property="sname" column="sname"/>
        <!--
        association:翻译为关联。一个Student对象关联一个Clazz对象
        property:提供要映射的POJO类属性名
        javaType:用来指定要映射的Java类型
        -->
       
        <association property="clazz" javaType="Clazz">
          <id property="cid" column="cid"/>
            <result property="cname" column="cname"/>
        </association>
    </resultMap>
    <select id="selectByIdAssociation" resultMap="studentResultMapAssociation">
           select
              s.sid,s.sname,c.cid,c.cname
           from
              t_student s left join t_clazz c on s.cid=c.cid
           where
              s.sid=#{sid}
    </select>

【测试样例】:

 @Test
    public void testStudentResultMapAssociation(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        Student student = mapper.selectByIdAssociation(1);
        System.out.println(student);
        sqlSession.close();
    }

三、第三种方式(两条SQL语句):分步查询

【注意】这种方式比较常用

【优点】:

  • 复用性强。可以重复使用。(把大步拆成N多小碎步。每一个小碎步也可重复利用)
  • 可以充分利用他们的延迟加载/懒加载机制

【什么是懒加载/延迟加载】

  • 原理是用的时候再执行查询语句。不用的时候不查询。
  • 提高性能:尽可能的不查,或者说尽可能少查。来提高效率。

【在mybatis中如何开启】

  •    association标签中添加fetchType="lazy"

【CarMapper.xml样例】:

第一步:先查出学生信息的所有信息,把信息当中的cid传给第二条查询语句

    <!--两条SQL语句,完成多对一的分布查询。-->
    <!--这里是第一步:根据学生的id查询学生的所有信息。这些信息当中含有班级的id-->
    <resultMap id="studentResultMapByStep" type="Student">
        <id property="sid" column="sid"/>
        <result property="sname" column="sname"/>
        <association property="clazz"
                     <!--select后面跟的是第二条语句的id(路径)-->
                     select="com.mapper.ClazzMapper.selectByIdStep2"
                     column="cid"/>
    </resultMap>

    <select id="selectByIdStep1" resultMap="studentResultMapByStep">
          select sid,sname,cid from t_student where sid=#{sid}
    </select>

第二步:第二条查询语句(根据第一步传过来的cid进行查询对应的课程信息)

    <!--分步查询第二步:根据cid获取班级信息。-->
<select id="selectByIdStep2" resultType="Clazz">
select  cid,cname from t_clazz where cid=#{cid}
</select>

【测试样例】:

@Test
    public void testSelectByIdStep1(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        Student student = mapper.selectByIdStep1(5);
        System.out.println(student);
    }

【注意】默认情况下是没有开启延迟加载的。需要设置:fetchType="lazy"

 <resultMap id="studentResultMapByStep" type="Student">
        <id property="sid" column="sid"/>
        <result property="sname" column="sname"/>
        <association property="clazz"
                     select="com.mapper.ClazzMapper.selectByIdStep2"
                     column="cid"
                     fetchType="lazy"/>
 </resultMap>

【注】当设置fetchType="lazy"之后,如果只需要看学生的名字,如:

System.out.println(student.getSname());

          此时,只会有一条SQL语句执行

select sid,sname,cid from t_student where sid=#{sid}

【注】当要看班级名时,如:

System.out.println("student.getClazz().getCname() = " + student.getClazz().getCname());

         此时就会执行两条SQL语句

select sid,sname,cid from t_student where sid=#{sid}
+
select  cid,cname from t_clazz where cid=#{cid}

association标签中的fetchType="lazy",是局部的设置,只对当前的association关联的SQL语句起作用。

在mybatis-config.xml中,作如下配置

 <settings>
        <setting name="lazyLoadingEnabled" value="true"/>
 </settings>

表示,开启延迟加载的全局开关。默认值false不开启。(所有的分步都采用延迟加载)

1.在实际的开发中,大部分都是需要使用延迟加载的,所以建议开启全部的延迟加载机制。

2.实际开发中的模式中通常都是把全局的开关打开,如果谁不需要延迟加载,就设置

fetchType="eager"