> 文章列表 > 十二、MyBatis的高级映射及延迟加载

十二、MyBatis的高级映射及延迟加载

十二、MyBatis的高级映射及延迟加载

1 数据库表的准备

准备数据库表:一个班级对应多个学生。班级表:t_clazz。学生表:t_stu
十二、MyBatis的高级映射及延迟加载
十二、MyBatis的高级映射及延迟加载

2 环境搭建

创建模块

打包方式:jar
引入依赖:mybatis依赖、mysql驱动依赖、junit依赖、logback依赖

配置文件:mybatis-config.xml、logback.xml、jdbc.properties
创建工具类:SqlSessionUtil
创建pojo类:Student、Clazz

package com.powernode.mybatis.pojo;/*** 学生信息*/
public class Student {private Integer sid;private String sname;private Clazz clazz;......//此处省略构造方法、getting setting toString方法
package com.powernode.mybatis.pojo;/*** 班级信息*/
public class Clazz {private Integer cid;private String cname;private List<Student> stus;......//此处省略构造方法、getting setting toString方法

创建mapper接口:StudentMapper、ClazzMapper
创建mapper映射文件:StudentMapper.xml、ClazzMapper.xml

3 多对一

十二、MyBatis的高级映射及延迟加载

多种方式,常见的包括三种:

  • 第一种方式:一条SQL语句,级联属性映射。
  • 第二种方式:一条SQL语句,association。
  • 第三种方式:两条SQL语句,分步查询。(这种方式常用:优点一是可复用。优点二是支持懒加载。)

第一种方式:级联属性映射

StudentMapper接口

package com.powernode.mybatis.mapper;import com.powernode.mybatis.pojo.Student;public interface StudentMapper {/*** 根据id获取学生信息,同时获取学生关联的班级信息* @param id 学生的id* @return 学生对象,但是学生对象里面含有班级对象*/Student selectById(Integer id);
}

StudentMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.powernode.mybatis.mapper.StudentMapper"><!--多对一映射的第一种方式:一条SQL语句,级联属性映射--><resultMap id="studentResulMap" type="Student"><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="studentResulMap">selects.sid,s.sname,c.cid,c.cnamefromt_stu s left join t_clazz c on s.cid = c.cidwheres.sid = #{sid}</select>
</mapper>

StudentMapperTest

package com.powernode.mybatis.test;import com.powernode.mybatis.mapper.StudentMapper;
import com.powernode.mybatis.pojo.Student;
import com.powernode.mybatis.utils.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;public class StudentMapperTest {@Testpublic void testSelectById(){SqlSession sqlSession = SqlSessionUtil.openSession();StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);Student student = mapper.selectById(1);System.out.println(student);sqlSession.close();}
}

第二种方式:association

association:关联。一个Student对象关联一个Clazz对象
property:提供要映射的POJO类的属性名
javaType:用来指定要映射的java类型

修改resultMap中的配置

 <!--一条SQL语句,association。-->
<resultMap id="studentResulMap" type="Student"><id property="sid" column="sid"/><result property="sname" column="sname"/><association property="clazz" javaType="Clazz"><id property="cid" column="cid"/><result property="cname" column="cname"/></association>
</resultMap>

第三种方式:分步查询

StudentMapper

/**
* 分布查询第一步:先根据学生的sid查询学生的信息
* @param id
* @return
*/
Student selectByIdStep1(Integer id);

StudentMapper.xml

property:pojo类中的属性名称
select:执行的sql语句的id
column:给select传参

<!--第一步:根据学生的id查询学生的所有信息,信息中含有班级的id-->
<resultMap id="studentResulMapByStep" type="Student"><id property="sid" column="sid"/><result property="sname" column="sname"/><association property="clazz"select="com.powernode.mybatis.mapper.ClazzMapper.selectByIdStep2"column="cid"></association>
</resultMap>
<select id="selectByIdStep1" resultMap="studentResulMapByStep">select sid,sname,cid from t_stu where sid = #{sid}
</select>

ClazzMapper

/**
* 分步查询第二步:根据cid获取班级信息* @param cid* @return*/
Clazz selectByIdStep2(Integer cid);

ClazzMapper.xml

<mapper namespace="com.powernode.mybatis.mapper.ClazzMapper"><!--分步查询第二步--><select id="selectByIdStep2" resultType="Clazz">select cid,cname from t_clazz where cid = #{cid}</select>
</mapper>

StudentMapperTest

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

分步查询的优点:
第一:复用性增强。可以重复利用。(大步拆成N多个小碎步。每一个小碎步更加可以重复利用。)
第二:采用这种分步查询,可以充分利用他们的延迟加载/懒加载机制。

4 延迟加载

什么是延迟加载(懒加载),有什么用

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

在mybatis当中怎么开启延迟加载

  • 局部设置

    <!--在association中设置的仅是局部设置-->
    <association fetchType="lazy">
    

    注意:默认情况下是没有开启延迟加载的。需要设置:fetchType=“lazy”
    在association标签中配置fetchType=“lazy”,是局部的设置,只对当前的association关联的sql语句起作用。

  • 全局配置
    在mybatis-config.xml核心配置文件中添加全局配置:lazyLoadingEnabled=true

    <settings><!--延迟加载的全局开关,默认值false不开启--><setting name="lazyLoadingEnabled" value="true"/>
    </settings>
    

    全局的延迟加载打开。
    如果某一步不需要使用延迟加载, 在association标签中配置fetchType=“eager”

    <association fetchType="eager">
    

5 一对多

一对多:一个班级对应多个学生(班级是主表,学生是副表)
十二、MyBatis的高级映射及延迟加载
一对多的实现通常包括两种实现方式:

  • 第一种方式:collection
  • 第二种方式:分步查询

第一种方式:collection

<resultMap id="clazzResultMap" type="Clazz"><id property="cid" column="cid"/><result property="cname" column="cname"/><!--一对多 collection 集合--><!--ofType 属性用来指定集合中的元素类型--><collection property="stus" ofType="Student"><id property="sid" column="sid"/><result property="sname" column="sname"/></collection></resultMap><select id="selectByIdCollection" resultMap="clazzResultMap">select c.cid,c.cname,s.sid,s.sname from t_clazz c left join t_stu s on c.cid = s.cid where c.cid = #{cid}</select>

第二种方式:分步查询

Clazz selectByStep1(Integer cid);
	<!--分步查询,据班级cid查询班级信息--><resultMap id="selectResultMapStep" type="Clazz"><id property="cid" column="cid"/><result property="cname" column="cname"/><collection property="stus"select="com.powernode.mybatis.mapper.StudentMapper.selectByCidStep2"column="cid"/></resultMap><select id="selectByStep1" resultMap="selectResultMapStep">select cid,cname from t_clazz where cid = #{cid}</select>
List<Student> selectByCidStep2(Integer cid);
<mapper namespace="com.powernode.mybatis.mapper.StudentMapper"><select id="selectByCidStep2" resultType="Student">select * from t_stu where cid = #{cid}</select>
</mapper>
@Test
public void testSelectByStep1(){SqlSession sqlSession = SqlSessionUtil.openSession();ClazzMapper mapper = sqlSession.getMapper(ClazzMapper.class);Clazz clazz = mapper.selectByStep1(1000);System.out.println(clazz);sqlSession.close();
}