⼗三、MyBatis的⾼级映射及延迟加载
模块名:mybatis-
010
-advanced-mapping
打包⽅式:jar
依赖:mybatis依赖、mysql驱动依赖、junit依赖、logback依赖
配置⽂件:mybatis-config.xml、logback.xml、jdbc.properties
拷⻉⼯具类:SqlSessionUtil
准备数据库表:⼀个班级对应多个学⽣。班级表:t_clazz。学⽣表:t_stu

创建好pojo:Student、Clazz
public class Clazz {
private Integer cid;
private String cname;
public Clazz(){}
public Clazz(Integer cid, String cname) {
this.cid = cid;
this.cname = cname;
}
//后面跟get,set,toString方法
//学生信息
public class Student {
private Integer sid;
private String sname;
public Student(){}
public Student(Integer sid, String sname) {
this.sid = sid;
this.sname = sname;
}
//后面跟get,set,toString方法
创建mapper接⼝:StudentMapper、ClazzMapper
创建mapper映射⽂件:StudentMapper.xml、ClazzMapper.xml
13.1 多对⼀
多种⽅式,常⻅的包括三种:
●
第⼀种⽅式:⼀条SQL语句,级联属性映射。
●
第⼆种⽅式:⼀条SQL语句,association。
●
第三种⽅式:两条SQL语句,分步查询。(这种⽅式常⽤:优点⼀是可复⽤。优点⼆是⽀持懒加
载。)
第⼀种⽅式:级联属性映射
pojo类Student中添加⼀个属性:Clazz clazz; 表示学⽣关联的班级对象。
public class Clazz {
private Integer cid;
private String cname;
private List<Student> stus;
public Clazz(){}
public Clazz(Integer cid, String cname) {
this.cid = cid;
this.cname = cname;
}
//后面跟get,set,toString方法
StudentMapper接口:
//根据id获取学生信息,同时获取学生关联的班级信息,返回学生对象,但是学生对象中含有班级对象
Student selectById(Integer id);
StudentMapper.xml:
<!-- 多对一映射的第一种方式:一条SQL语句,联机属性映射 -->
<resultMap id="studentResultMap" type="Student">
<id property="sid" column="sid"></id>
<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_stu s
left join t_clazz c on s.cid = c.cid
where s.sid = #{sid}
</select>
StudentMapperTest:
@Test
public void testSelectById(){
SqlSession sqlSession = SqlSessionUtil.openSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student student = mapper.selectById(1);
System.out.println(student.getSid()); //1
System.out.println(student.getSname()); //张三
System.out.println(student.getClazz().getCid()); //1000
System.out.println(student.getClazz().getCname()); //大数据201
System.out.println(student);
sqlSession.close();
}
第⼆种⽅式:association
其他位置都不需要修改,只需要修改resultMap中的配置:association即可。
StudentMapper接口:
//一条SQL,association
Student selectByIdAssociation(Integer id);
StudentMapper.xml:
<!-- ⼀条SQL语句,association。-->
<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_stu s
left join t_clazz c on s.cid = c.cid
where s.sid = #{sid}
</select>
StudentMapperTest:
@Test
public void testSelectByIdAssociation(){
SqlSession sqlSession = SqlSessionUtil.openSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student student=mapper.selectByIdAssociation(2);
System.out.println(student);
sqlSession.close();
}
第三种⽅式:分步查询
其他位置不需要修改,只需要修改以及添加以下三处:
第⼀处:association中select位置填写sqlId。sqlId=namespace+id。其中column属性作为这条⼦sql语句的条件。
第⼆处:在ClazzMapper接⼝中添加⽅法
第三处:在ClazzMapper.xml⽂件中进⾏配置
StudentMapper接口:
//分步查询第一步:先根据学生的sid查询学生的信息
Student selectByIdStep1(Integer id);
StudentMapper.xml:
<!-- 两天SQL语句,完成多对一的分步查询 -->
<!-- 这里是第一步:根据学生的id查询学生的所有信息,这些信息当中含有班级id(cid) -->
<!--
分步查询的优点:
第一:复用性增强。可以重复利用。(大步拆成N多个小碎步。每一个小碎步更加可以重复利用。)
第二:采用这种分步查询,可以充分利用他们的延迟加载/懒加载机制。
什么是延迟加载(懒加载),有什么用?
延迟加载的核心原理是:用的时候再执行查询语句。不用的时候不查询。
作用:提高性能。尽可能的不查,或者说尽可能的少查。来提高效率。
在mybatis当中怎么开启延迟加载呢?
association标签中添加fetchType="lazy"
注意:默认情况下是没有开启延迟加载的。需要设置:fetchType="lazy"
这种在association标签中配置fetchType="lazy",是局部的设置,只对当前的association关联的sql语句起作用。
在实际的开发中,大部分都是需要使用延迟加载的,所以建议开启全部的延迟加载机制:
在mybatis核心配置文件中添加全局配置:lazyLoadingEnabled=true
实际开发中的模式:
把全局的延迟加载打开。
如果某一步不需要使用延迟加载,请设置:fetchType="eager"
-->
<resultMap id="studentResultMapByStep" type="student">
<id property="sid" column="sid"/>
<result property="sname" column="sname"/>
<association property="clazz"
select="com.powernode.mybatis.mapper.ClazzMapper.selectById"
column="cid"/>
</resultMap>
<select id="selectByIdStep1" resultMap="studentResultMapByStep">
select sid,sname,cid from t_stu where sid = #{sid}
</select>
ClazzMapper接口:
//分步查询第二步:根据cid获取班级信息
Clazz selectById(Integer cid);
ClazzMapper.xml:
<!-- 分步查询第二部:根据cid获取班级信息 -->
<select id="selectById" resultType="Clazz">
select cid, cname
from t_clazz
where cid = #{cid}
</select>
StudentMapperTest:
@Test
public void testSelectByIdStep1(){
SqlSession sqlSession = SqlSessionUtil.openSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student student =mapper.selectByIdStep1(5);
//第一步:Preparing: select sid,sname,cid from t_stu where sid = ?
//第二步:Preparing: select cid, cname from t_clazz where cid = ?
System.out.println(student);
sqlSession.close();
}
分步优点:
●第⼀个优点:代码复⽤性增强。
●第⼆个优点:⽀持延迟加载。【暂时访问不到的数据可以先不查询。提⾼程序的执⾏效率。】
13.2 多对⼀延迟加载
要想⽀持延迟加载,⾮常简单,只需要在association标签中添加fetchType="lazy"即可。
修改StudentMapper.xml⽂件:
StudentMapper.xml:
<!-- 什么是延迟加载(懒加载),有什么用?
延迟加载的核心原理是:用的时候再执行查询语句。不用的时候不查询。
作用:提高性能。尽可能的不查,或者说尽可能的少查。来提高效率。
在mybatis当中怎么开启延迟加载呢?
association标签中添加fetchType="lazy"
注意:默认情况下是没有开启延迟加载的。需要设置:fetchType="lazy"
这种在association标签中配置fetchType&#