【Mybatis架构】 延迟加载

 在上一篇博客中,我们提到过有关于Mybatis输出映射中resultMap能够实现延迟加载的事,然而真的是所有的resultMap都能实现延迟加载还是咋地啊?现在我们就来对那一句话做一下阐述和实例说明。

 

一、首先我们要知道什么是延迟加载?

       延迟加载机制是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作;可以简单理解为,只有在使用的时候,才会发出sql语句进行查询;延迟加载的有效期是在session打开的情况下,当session关闭后,会报异常。当调用load方法加载对象时,返回代理对象,等到真正用到对象的内容时才发出sql语句。

 

总结:需要查询关联信息时,使用mybatis延迟加载特性可有效的减少数据库压力,首次查询只查询主要信息,              关联信息等用户获取时再加载。我们已知的除了hibernate,还有我们的Mybatis。

 

二、实战演练场:

(1)需求:还以我们的上面两篇文章的电商项目查询订单信息为例,这次,我们以订单信息为主要查询表,然后关联查询对应的用户信息。那什么是延迟加载呢,就是我们默认先只查询订单信息,当我们需要客户信息的时候呢,我们再去关联查询用户信息。这就是延迟加载了。

 

(2)pojo类的设计:

首先是订单类:

 

  1. public class Orders {  
  2.     private Integer id;  
  3.     private Integer userId;  
  4.     private String number;  
  5.     private Date createtime;  
  6.     private String note;  
  7.     private User user;  
  8.     //getter、setter  
  9. }  
用户信息类:

 

 

  1. public class User {  
  2.     private int id;  
  3.     private String username;  
  4.     private int sex;  
  5.     private Date birthday;  
  6.     private String address;  
  7.     //getter、setter  
  8. }  
再就是我们Mapper映射文件离间对resultMap的定义:

 

 

  1. <pre code_snippet_id="2062392" snippet_file_name="blog_20161220_3_5346738" name="code" class="html"><resultMap type="com.ssm.mybatis.po.Orders" id="selectOrderUserLazyLoading">  
  2.         <!-- 配置映射的订单信息 -->    
  3.         <id column="id" property="id"/>  
  4.         <result column="user_id" property="userId"/>  
  5.         <result column="number" property="number"/>  
  6.         <result column="createtime" property="createtime"/>  
  7.         <result column="note" property="note"/>  
  8.   
  9.         <!-- 配置映射的用户信息 -->  
  10.         <association property="user" javaType="com.ssm.mybatis.po.User"   
  11.              select="com.ssm.mybatis.mapper.UserMapper.findUserById" column="user_id">             
  12.         </association>  
  13.     </resultMap></pre><br>  
  14. <br>  
  15. <pre></pre>  
  16. <p></p>  
  17. <pre></pre>  
  18. <p></p>  
  19. <pre></pre>  
  20. <pre></pre>  

在这里,注意我们的配置映射的映射信息里面有一个select属性,这里实现的就是我们的延迟加载,后面就是我们定义的查询用户信息的Mapper的命名空间,也可以说是一个指向。

 

配置文件里面statement对resultMap的调用配置:
  1. <select id="selectOrderUserLazyLoading" resultMap="OrderUserLazyLoadingResultMap" >  
  2.         select * from orders  
  3. </select>  

接下来,我们定义一个mapper接口进行测试

 

  1. public interface OrdersMapper{  
  2.     List<Orders> findOrderUserLazyLoading() throws Exception;  
  3. }  
测试:

 

 

  1. @Test  
  2. public void selectOrderUserLazyLoading(){  
  3.     SqlSession session=sqlSessionFactory.openSession();  
  4.     OrdersMapperCustom ordersMapperCustomMapper=session.getMapper(OrdersMapperCustom.class);  
  5.     try {  
  6.         List<Orders> list=ordersMapperCustomMapper.findOrderUserLazyLoading();//查询订单信息  
  7.         if (list!=null) {//此处有断点  
  8.                 System.out.println(list.get(0).getUser().getUsername());//查询第一个订单的用户信息  
  9.         }  
  10.     } catch (Exception e) {//此处有断电  
  11.         e.printStackTrace();  
  12.     }  
  13. }  
在上面的测试代码里面,我们执行断点查询,分别在if和catch上打一个端点,看tomcat的日志信息

 

大家可以看到,当我们执行到第一个断点的时候,这里mybatis只发出一条查询订单信息的sql去查询所有的订单信息。接下来,我们继续往下走:

大家看到了,当我们执行到想要获取第一个订单的用户信息时,它又发出了另一条根据id查询用户信息的sql,也就是说,当我们需要调用用户信息的查询方法时,它才会才会去执行查询,这也就是我们所说的延迟加载,也叫做懒加载。大家可以很明显的看到,在这里我们使用的association来实现的延迟加载,其使用collection也一样,至于使用association和collection有什么区别呢,前面我们也介绍过,association是将关联信息映射到一个pojo对象中,而collection是将关联消息映射到list结合中,就这么简单的理由

 

三、如何配置Mybatis延迟加载(懒加载)

      首先我们要知道,Mybatis默认是不支持执行延迟加载(懒加载)的,这需要我们手动去配置,去打开开关。而我们可以总结一下,但我们需要设置开启二级缓存的时候,我们首先需要在Mybatis全局配置文件也就是我们的sqlMapConfig.xml中去设置开启二级缓存,然后再去每个具体mapper映射文件中去确认本映射文件开启二级缓存,也就是所有的全局性的功能或者是性能配置总阀门都在全局配置文件中的。所以我们是否开启延迟加载的这一项功能也是在sqlMapConfig.xml中进行配置:

 

  1. <settings>  
  2.    <setting name="lazyLoadingEnabled" value="true"/><!--延迟加载/懒加载-->  
  3.    <setting name="aggressiveLazyLoading" value="false"/><!--积极加载/预加载-->  
  4. </settings>  
然后如何在禁止懒加载的配置就不用再介绍了吧。

 

 

另外呢,通过看师哥师姐的博客以及外面人的介绍,mybatis的全局配置文件中的标签是有先后顺序的,按序分别是:properties、settings、typeAlliases、typeHandlers、objectFactory、plugins、environments、mappers。究竟是为什么呢,为了探究这个问题,我故意使用原生的mybatis(不与spring整合)配错一个,结果真的如是个所说,报错:

"元素类型为configuration的内容必须匹配(properties?,settings?,typeAliases?,typeHandlers?……"

相关知识:http://www.cnblogs.com/selene/p/4607004.html

 

四、总结:

       以上,就是我们mybatis实现延迟加载的一个简单介绍,那现在回答刚开头时问的问题,是所有的resultMap都能实验延迟加载吗?答案是:mybatis中能实现延时加载的是resultMap,弹死不是所有的resultMap都必须实现延时加载,我们利用的是resultMap里面的association和collection来实现的延迟加载。另外毕竟小编研究mybatis时间不长,难免有所疏漏,若有不足,还请各位指正,必及时修改。

posted @ 2017-01-02 21:22  Double-Eggs  阅读(2910)  评论(-1编辑  收藏  举报