MyBatis中的延迟加载策略

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>
<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">resultMap</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">select </span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="getSmbmsBillList"</span><span style="color: #ff0000;"> resultMap</span><span style="color: #0000ff;">="SmbmsProviderResult"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;">
    select * from  smbms.smbms_bill where id=#{id}
</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">select</span><span style="color: #0000ff;">&gt;</span>
<span style="color: #0000ff;">&lt;</span><span style="color: #800000;">select </span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="getSmbmsProvider"</span><span style="color: #ff0000;"> resultType</span><span style="color: #0000ff;">="SmbmsProvider"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;">
    select * from  smbms.smbms_provider where  id=#{providerId}
</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">select</span><span style="color: #0000ff;">&gt;</span>

</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的延迟加载机制的理解,有不足之处还请指出

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: MyBatis 延迟和饥饿的区别在于: - 延迟(Lazy Loading):在需要时才数据,即当访问一个对象的关联对象时才会真正发出 SQL 语句去查询。 - 饥饿(Eager Loading):在查询时立即数据,即在查询主对象时同时查询出关联对象。 延迟常用于大量数据时,以节约内存;而饥饿常用于需要立即访问关联对象的情况。你可以通过配置 XML 文件或注解来设置方式。 ### 回答2: MyBatis延迟和饥饿是两种不同的策略延迟是指在查询执行时,仅主实体对象的基本属性,而关联的子实体对象的属性只有在使用时才会根据需要进行。也就是说,当我们执行一个查询时,如果查询结果包含了某个实体的关联对象,那么在使用这个关联对象时才会触发去该对象,否则不会进行操作。这种方式可以减少不必要的查询操作,提高性能。 饥饿则是指在查询执行时,除了主实体对象的基本属性之外,还会立即所有关联的子实体对象的属性。这种方式会在执行查询时同时进行外键关联查询,以提前所有的关联对象。虽然可以避免懒导致的性能问题,但是同时也会增查询的复杂度和查询结果的冗余。 从使用的角度来看,延迟适用于关联对象较多且查询性能较为重要的情况下,可以避免不必要的查询操作;而饥饿则适用于关联对象较少或者需求需要立即所有关联对象的情况下,可以减少查询时的多余查询次数。 总结起来,延迟和饥饿MyBatis是两种不同的关联对象策略延迟只在使用到关联对象时才会进行,而饥饿则在查询时即立即所有的关联对象属性。根据实际需求和性能考虑,我们可以选择合适的策略来优化查询性能和减少不必要的查询操作。 ### 回答3: MyBatis延迟(Lazy Loading)和饥饿(Eager Loading)是两种不同的策略延迟是指在需要使用到关联对象时才进行,可以减少数据库查询次数和提高性能。例如,在查询一篇文章的同时,延迟可以在需要读取作者信息时才去数据库查询作者的详细信息。这样可以避免在不需要使用作者信息时额外的数据库查询。延迟的实现方式是使用代理对象,在真正需要使用到关联对象时才会触发数据库查询。 饥饿是指在查询主对象的同时,将关联对象也一起,即使在查询过程可能并不需要使用到这些关联对象。这样可以提高后续查询时的性能,但可能会产生额外的数据库查询负担。例如,在查询一篇文章的同时,饥饿可以将作者信息一并,即使在读取文章时并不需要使用作者信息。 延迟和饥饿各有优劣。延迟可以减少额外的数据库查询,节省资源,但在真正需要使用到关联对象时会产生额外的查询时间延迟。饥饿可以提高查询性能,但会增数据库查询的负担和资源消耗。 在实际应用,可以根据具体场景选择合适的策略。如果对性能要求较高,并且关联对象的查询概率较大,可以选择饥饿。如果对性能要求相对较低,并且关联对象的查询概率较小,可以选择延迟,以降低数据库查询压力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值