MyBatis--延迟加载

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());
    }
}

三、深度延迟加载

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

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

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

四、侵入式延迟加载

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

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

测试类:

@Test
public 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无论取何值,均不起作用。

五、延迟加载策略总结

延迟加载.PNG
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 延迟加载 延迟加载处理的是N+1性能问题,所谓N+1性能问题指的是映射集合(resultMap)内存在级联时,我们...
    fanyank阅读 3,621评论 0 2
  • 需求: 现有用户表和订单表,订单表相对于用户表是一对一映射,我们查询订单时,不查订单用户,只有在使用订单的用户信息...
    司鑫阅读 1,769评论 0 3
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 176,328评论 25 709
  • 深夜,月圆,晚风,第一次抽烟的女孩。 她从小到大一直在别人眼里是一个好女孩、乖女孩、听话的女孩,可是今夜她抽了一支...
    慕暄和阅读 1,837评论 0 0
  • 看到群里有人问popToViewController的用法 就写了下了 希望能帮到有需要的人
    武一顶顶阅读 3,627评论 0 1

友情链接更多精彩内容