mybatis 的延迟加载

来源:互联网 发布:手机wifi控制器软件 编辑:程序博客网 时间:2024/06/05 20:03

mybatis 的延迟加载

(1)什么是延迟加载?

延迟加载,也称为懒加载(LazyLoding)。
当代码中执行到查询语句时,并不是直接到DB中执行select语句进行查询,而是根据设置好的延迟策略,将查询向后推迟。这就称为延迟加载。
使用延迟加载可以减轻DB服务器的压力。

resultMap中的association和collection标签具有延迟加载的功能

(2)Mybatis的延迟加载功能     

 MyBatis的延迟加载
         1)只能对关联对象进行查询时,使用延迟加载策略。对于主加载对象,均采用直接加载。
         2)要应用延迟加载查询,只能使用多表单独查询而不能使用多表连接查询。因为多表连接查询的本质是查询一张表,将多张表首先连接为了一张表后,再进行的查询。 查询一个信息,就会将所有信息全部查询到。

 (3) 基本概念

         1)主加载对象  
如: country (国家) 一方  根据国家的id 去查询部长
         2)关联对象
如:minister(部长)多方    根据国家的id 去查询部长 
         3)主表
如:country 表
         4)关联表,也称为从表
如:minister 表

 (4) Mybatis延迟加载策略-三种

         延迟加载策略是指到DB中真正执行select语句进行查询的时机设置。
         MyBatis中的延迟加载策略共分三种:
         1)直接加载:代码中执行到查询语句,马上就到DB中执行select查询。
         2)侵入式延迟加载(lazyLoadingEnabled = true ,aggressiveLazyLoading  = true [ə'gresɪv]):将关联对象的详情侵入到了主加载对象详情之中,作为主加载对象的详情的一部分出现。当要访问主加载对象的详情时,需要将主加载对象所有详情进行查询,但由于关联对象详情作为主加载对象详情的一部分出现了,所以,这个查询不仅会查询主表,还会查询关联表。(对象详情既就是对象的数据)
         3)深度延迟加载(lazyLoadingEnabled = true, aggressiveLazyLoading = false):当需要访问主加载对象详情时,只会查询主表,而不会查询关联表。只有当真正访问关联对象详情时,才会查询关联表。

(5)Mybatis 延迟加载的开启方式

Mybatis在核心配置文件(mybtais.xml)提供了一个 settings 标签,用于设置Mybtais的属性,改变Mybatis的状态。其中有两个属性字段是用于延迟加载的,分别是 lazyLodingEnabled和aggressiveLazyLoding。

图1mybatis 中文官方文档settings标签中的延迟加载
详解:
LazyLodingEnabled 延迟加载的总开关,aggressiveLazyLoading 侵入式延迟加载的开关
侵入式延迟加载不开启既aggressiveLazyLoading = false,就是自动开启了深度加载。
注意:
在mybatis 版本4.1.3 版本以下,aggressiveLazyLoading 的默认值为true,既默认开启了侵入式延迟加载。
在mybatis 版本4.1.3 版本以上,aggressiveLazyLoading 的默认值为false,既默认不开启侵入式延迟加载。

 (5.1)Mybatis 延迟加载在项目的设置

    1)在mybatis.xml 中开启全局的延迟加载和侵入式的延迟加载
         注意:settings 配置的位置需要在别名(typeAliases)配置之前
  1. <settings>
  2. <!-- 延迟加载的总开关 -->
  3. <setting name="lazyLoadingEnabled" value="true"/>
  4. <!-- 侵入式延迟加载开关:延迟加载总开关在开启状态下,本开关才起作用 -->
  5. <setting name="aggressiveLazyLoading" value="true"/>
  6. </settings>

图2settings配置的位置

    2)测试关联对象的侵入式延迟加载    
        条件:开启延迟加载总开关(lazyLoadingEnabled =  true)
                  开启侵入式延迟加载(aggressiveLazyLoading = true)
        测试:mapper.xml(对于关联对象,必须使用多表单独查询)
  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.abc.dao.ICountryDao">
  6. <!-- 多表单独查询 -->
  7. <select id="selectMinisterByCountry" resultType="Minister">
  8. select mid,mname from minister where countryId=#{ooo}
  9. </select>
  10. <!-- 定义结果映射关系 -->
  11. <resultMap type="Country" id="countryMap">
  12. <id column="cid" property="cid"/>
  13. <result column="cname" property="cname"/>
  14. <!-- ofType解释为element of type ,元素类型 -->
  15. <collection property="ministers"
  16. ofType="Minister"
  17. select="selectMinisterByCountry"
  18. column="cid"/>
  19. </resultMap>
  20. <select id="selectCountryById" resultMap="countryMap">
  21. select cid,cname from country where cid=#{xxx}
  22. </select>
  23. </mapper>
          测试代码:
图3侵入式延迟加载测试代码
在debug 模式下,当执行完syso(country.getCname()) 的时候,第二条查询语句就已经执行了。注意,这里是执行完这一句代码之后,mybatis才对关联对象进行查询。
这也就是侵入式延迟加载,把我们的关联对象的详情侵入到了主加载对象中了,导致我们查询主加载对象的详情的时候关联对象的信息也被加载了。
结果:

图4侵入式延迟加载测试结果
 
    3)测试关联对象的深度延迟加载
        条件:开启延迟加载的总开关(lazyLoadingEnabled =  true)
                  关闭侵入式延迟加载的开关(aggressiveLazyLoading = false)
        测试:mybatis.xml配置文件
  1. <settings>
  2. <!-- 延迟加载的总开关 -->
  3. <setting name="lazyLoadingEnabled" value="true"/>
  4. <!-- 侵入式延迟加载开关:延迟加载总开关在开启状态下,本开关才起作用 -->
  5. <setting name="aggressiveLazyLoading" value="false"/>
  6. </settings>
        执行

图5深度延迟加载测试
       当需要访问主加载对象详情时,只会查询主表,而不会查询关联表。只有当真正访问关联对象详情时,才会查询关联表。

原创粉丝点击