Mybatis 延迟加载详解

MyBatis中的延迟加载,也称为懒加载,是指在进行关联查询时,按照设置延迟规则推迟对关联对象的select查询。延迟加载可以有效的减少数据库压力。

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

一、关联对象加载时机

MyBatis根据对关联对象查询的select语句的执行时机,分为三种类型:直接加载、侵入式加载与深度延迟加载

  • 直接加载:执行完对主加载对象的select语句,马上执行对关联对象的select查询。
  • 侵入式延迟:执行对主加载对象的查询时,不会执行对关联对象的查询。但当要访问主加载对象的详情时,就会马上执行关联对象的select查询。即对关联对象的查询执行,侵入到了主加载对象的详情访问中。也可以这样理解:将关联对象的详情侵入到了主加载对象的详情中,即将关联对象的详情作为主加载对象的详情的一部分出现了。
  • 深度延迟:执行对主加载对象的查询时,不会执行对关联对象的查询。访问主加载对象的详情时也不会执行关联对象的select查询。只有当真正访问关联对象的详情时,才会执行对关联对象的select查询。

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

二、直接加载

1.主配置文件(Mybatis.xml)

全局属性lazyLoadingEnabled的值只要设置为false,那么,对于关联对象的查询,将采用直接加载。即在查询过主加载对象后,会马上查询关联对象。

lazyLoadingEnabled的默认值为false,即直接加载。

<settings>    <!-- 延迟加载总开关 -->    <setting name="lazyLoadingEnabled" value="false"/></settings>

2.mapper映射文件

<mapper namespace="com.hcx.dao.IMinisterDao">    <select id="selectCountryById" resultType="Country">        select cid,cname from country where cid=#{cid}    </select>    <resultMap type="Minister" id="ministerMapper">        <id column="mid" property="mid"/>        <result column="mname" property="mname"/>        <association property="country"                     javaType="Country"                     select="selectCountryById"                     column="countryId"/>    </resultMap>    <select id="selectMinisterById" resultMap="ministerMapper">        select mid,mname,countryId from minister where mid=#{mid}    </select></mapper>

3.测试类:

当程序执行到断点处语句时,不仅对country表进行了查询,对minister表也同时进行了查询。

public class MyTest {    private ICountryDao dao;    private SqlSession session;    @Before    public void setUp(){        session = MyBatisUtils.getSqlSession();        dao = session.getMapper(ICountryDao.class);    }    @After    public void tearDown(){        if(session!=null){            session.close();        }    }    @Test    public void test01(){               Country country = dao.selectCountryById(2);        //此处加断点        System.out.println(country);        System.out.println(country.getMinisters().size());    }}

三、深度延迟加载

修改主配置文件的,将延迟加载开关lazyLoadingEnabled开启(置为true),将侵入式延迟加载开关aggressiveLazyLoading关闭(置为false)。

<settings>    <!-- 延迟加载总开关 -->    <setting name="lazyLoadingEnabled" value="true"/>    <!-- 侵入式延迟加载开关 -->    <setting name="aggressiveLazyLoading" value="false"/></settings>

此时,只有当代码执行到输出Minister对象详情时,底层才执行select语句对minister表进行查询。

四、侵入式延迟加载

修改主配置文件的,将延迟加载开关lazyLoadingEnabled开启(置为true),将侵入式延迟加载开关aggressiveLazyLoading也开启(置为true,默认为true)。

<settings>    <!-- 延迟加载总开关 -->    <setting name="lazyLoadingEnabled" value="true"/>    <!-- 侵入式延迟加载开关 -->    <setting name="aggressiveLazyLoading" value="true"/></settings>

测试类:

@Testpublic void test01(){           Country country = dao.selectCountryById(2);    //此处加断点    System.out.println(country);    System.out.println(country.getMinisters().size());}

当代码执行断点处语句时会立即查询country表,但每查询minister表。说明现在的延迟加载已经启动。
当对country对象的详情进行访问时,对minister表也进行了查询。因为该延迟加载策略已经将主加载对象的关联属性也作为主加载对象的基本信息了,而前面已经查询出了主加载对象的基本信息,但其关联对象基本信息尚无。所以,马上进行对minister表的查询。
换个角度来说,该延迟策略使关联对象的数据侵入到了主加载对象的数据中,所以称为侵入式延迟加载。

注意:该延迟策略也是一种延迟加载,需要在延迟加载开关lazyLoadingEnabled开启时才会起作用。若lazyLoadingEnabled为false,则aggressiveLazyLoading无论取何值,均不起作用。

五、延迟加载策略总结

(0)

相关推荐

  • 图解MyBatis

    回复"面试"获取全套面试资料 在以前文章中,我们对Mybatis进行了入门级的介绍教小师妹快速入门Mybatis,看这篇就够了,今天我们来从一个全局的角度看看Mybatis. 本文 ...

  • Mybatis中mapper的xml解析详解

    上一篇文章分析了mapper注解关键类MapperAnnotationBuilder,今天来看mapper的项目了解析关键类XMLMapperBuilder. 基础介绍 回顾下之前是在分析config ...

  • Mybatis初始化过程简单总结

    前面连续多篇文章都是在数据mybatis的初始化过程,目前基本完成,是时候做一个总结了. 总览 首先回顾下最上层的测试代码,实际上目前分析的还在测试代码中与mybatis相关的第一步,具体如下图: 目 ...

  • spring与mybatis整合详解

    spring与mybatis整合详解 在数据库dbmis中创建student表: 建立Maven项目,创建Dao层,POJO层,Controller层,并配置Mapper.applicationCon ...

  • (三)MyBatis从入门到入土——使用详解

    MyBatis使用详解 上篇我们手动开发了一个MyBatis项目,但是我们仅仅是编写了代码,对于整个项目是如何运行以及每个代码的意义都没有仔细的分析和说明,那么接下来我们就开始分析每个代码的意义以及如 ...

  • 写了10年的代码,我最怕写Mybatis这些配置,现在有详解了

    在使用 mybatis 过程中, 当手写 JavaBean和XML 写的越来越多的时候, 就越来越同意出错.这种重复性的工作, 我们当然不希望做那么多. 还好, mybatis 为我们提供了强大的代码 ...

  • Mybatis的sql组装详解

    上一篇分析了SqlSession执行sql的过程,其中并没有分析sql是从哪里来的,今天就来仔细分析下. Sql来源 从上一篇的最后一步执行sql那里倒推sql的来源,源码主要过程如下图: 可以看到最 ...

  • 建议收藏,mybatis插件原理详解

    回复"面试"获取全套面试资料 上次发文说到了如何集成分页插件MyBatis插件原理分析,看完感觉自己better了,今天我们接着来聊mybatis插件的原理. 插件原理分析 myb ...

  • Mybatis的SqlSession创建过程详解

    前面mybatis的初始化过程分析完成,接下来是第二步SqlSession的创建. 创建过程总览 SqlSession创建过程如下图: 创建过程还是比较简单的,首先是之前分析的SqlSessionFa ...

  • Mybatis中SqlSource解析流程详解

    前面几篇文章都在详细分析mapper的加载过程,但是始终没有看到sql的解析过程,今天来详细分析下. 解析sql的位置 前面分析到不管是通过注解还是通过xml方式生成mapper,最终都是调用Mapp ...

  • Mybatis中mapper相关注解解析类详解

    上一篇文章分析发现解读mapper关键是两个类MapperAnnotationBuilder和XMLMapperBuilder,今天先来看MapperAnnotationBuilder. 基础介绍 根 ...