MyBatis中的延迟加载策略

一:延迟加载

1.了解延迟加载:

延迟加载又叫懒加载,也叫按需加载,也就是说先加载主信息,需要的时候,再去加载从信息。代码中有查询语句,当执行到查询语句时,并不是马上去DB中查询,而是根据设置的延迟策略将查询向后推迟。

2.延迟加载的好处:

先从单表查询、需要时再从关联表去关联查询,大大提高数据库性能,减轻数据库服务器的压力,因为查询单表要比关联查询多张表速度要快。

3.如何开启MyBatis的延迟加载:

Mybatis的延迟加载功能默认是关闭的

需要在mybatis-config.xml(mybatis的核心配置)文件中通过setting标签配置来开启延迟加载功能

 

<settings>
<!--开启延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--value为true时为侵入式延迟加载,false为深入式延迟加载-->
<setting name="aggressiveLazyLoading" value="true"/>
</settings>

4.延迟加载的resultMap

4.1当在resultMao中使用过association或者collection进行关系映射之后才能使用MyBatis的延迟加载策略

4.2 延迟加载需要两个select语句来完成

关联对象的查询与主加载对象的查询必须是分别进行的select语句,不能是使用多表连接所进行的select查询。因为,多表连接查询,实质是对一张表的查询,对由多个表连接后形成的一张表的查询。会一次性将多张表的所有信息查询出来。

5.关联对象的加载时机

MyBatis的延迟加载只是对关联对象的查询有延迟设置,对于主加载对象都是直接执行查询语句的。

1.直接加载

即执行对象的select语句,完成对主加载马上执行对关联对象的select查询。

2.侵入式延迟加载(aggressiveLazyLoading) 也可看做立即加载

执行对主加载对象的查询时,不会执行对关联对象的查询。但是当要访问主加载对象的详情时马上执行对关联对象的select查询。即对关联对象的执行查询,侵入到了主加载对象的访问详情中。也可理解为:将关联对象的详情侵入到主加载对象的详情中去,即将关联对象的详情作为主加载对象的一部分出现了!

3.深度延迟加载

执行对主加载对象的查询时,不会执行对关联对象的查询。访问主加载对象的详情时也不会执行关联对象的select查询。只有当真正访问关联对象的详情时,才会执行对关联对象的select查询。

六:延迟加载测试案例

1.将俩张表的关联关系在实体类中体现出来,也就是在一张表中添加另一张表的对象

 

 

2.创建Dao层的方法一级Mapper.xml文件

 

 

 

 

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yjc.dao.ISmbmsDao">
    <resultMap id="SmbmsProviderResult" type="SmbmsBill">
        <collection property="smbmsProvider" ofType="SmbmsProvider" select="getSmbmsProvider" column="providerId">
        </collection>

    </resultMap>
    <select id="getSmbmsBillList" resultMap="SmbmsProviderResult">
        select * from  smbms.smbms_bill where id=#{id}
    </select>
    <select id="getSmbmsProvider" resultType="SmbmsProvider">
        select * from  smbms.smbms_provider where  id=#{providerId}
    </select>

</mapper>

3.测试类

public class YiTest {
    public static void main(String[] args) {
        SqlSession session = SqlSessionUtils.getSession();
        ISmbmsDao mapper = session.getMapper(ISmbmsDao.class);
        SmbmsBill smbmsBillList = mapper.getSmbmsBillList(1);
}
}

当没有开启延迟加载策略的时候,MyBatis默认是直接加载当执行上面的测试类的时候结果如下

1.直接加载

 

 

 如上图所示,一共向数据库发送了两条请求,此时我们开启侵入式延迟加载 然后再执行上面的测试

2.侵入式延迟加载

<settings>
<!--开启延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--value为true时为侵入式延迟加载,false为深入式延迟加载-->
<setting name="aggressiveLazyLoading" value="true"/>
</settings>

此时测试的结果如下

 

 由于我们只进行了查询操作,并没有对查询出来的主对象进行操作(访问改对象的属性或及方法)所以此时并没有进行加载关联的查询

那么我们接下来访问一些主对象的一些属性

结果如下

 

 

这就是侵入式延迟加载的效果,当对主加载对象进行操作的时候就会去加载关联对象(向数据库发送请求)

3.深度式延迟加载

在核心配置文件中修改setting节点

          <!--开启延迟加载-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!--value为true时为侵入式延迟加载,false为深入式延迟加载-->
        <setting name="aggressiveLazyLoading" value="false"/>    

修改完成之后继续执行上次执行的测试方法

 

 从上面的结果中可以看到同样的测试方法,开始深度式延迟之后只向数据库发送了一次请求,这是因为我们在测试类中只访问了主对象的属性,并没有使用关联对象的任何属性

那么接下来我们修改测试类,在测试类中添加对关联对象的访问

public class YiTest {
    public static void main(String[] args) {
        SqlSession session = SqlSessionUtils.getSession();
        ISmbmsDao mapper = session.getMapper(ISmbmsDao.class);
        SmbmsBill smbmsBillList = mapper.getSmbmsBillList(1);
        //获取关联对象中的proName属性
        System.out.println(smbmsBillList.getSmbmsProvider().getProName());

    }
}

测试结果如下

 

 当我们访问关联对象时候就发送请求进行对关联关系的加载,这就是MyBatis中的深度式延迟加载策略

以上就是我对MyBatis的延迟加载机制的理解,有不足之处还请指出

 

posted @ 2019-10-14 15:39  天戈  阅读(931)  评论(0编辑  收藏  举报