延迟加载其实就是将数据加载时机推迟,比如推迟嵌套查询的执行时机。在Mybatis中经常用到关联查询,但是并不是任何时候都需要立即返回关联查询结果。比如查询订单信息,并不一定需要及时返回订单对应的产品信息,查询商品分类信息并不一定要及时返回该类别下有哪些产品,这种情况一下需要一种机制,当需要查看时,再执行查询,返回需要的结果集,这种需求在Mybatis中可以使用延迟加载机制来实现。延迟加载可以实现先查询主表,按需实时做关联查询,返回关联表结果集,一定程度上提高了效率。

Mapper.xml映射文件

以商品类别category和商品product为例,一个类别下可以有多个商品,一个商品属于一种类别。

编写lazyLoadMapper.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.sl.mapper.LazyLoadMapper">
<!-- 分类信息查询 -->
<select id="lazyLoadTest" resultMap="lazyLoadProductsByCategoryTest">
select * from category where id=#{id}
</select>
<resultMap id="lazyLoadProductsByCategoryTest" type="com.sl.po.Category">
<id column="id" property="Id"></id>
<result column="name" property="Name"></result>
<result column="remark" property="Remark"></result>
<!-- 一个分类对应多个产品,此处使用collection -->
<collection property="productList" ofType="com.sl.po.Product" column="id" select="selectProductsByCategoryId"></collection>
</resultMap> <!-- 嵌套查询返回商品信息,延迟加载将要执行的sql -->
<select id="selectProductsByCategoryId" resultType="com.sl.po.Product">
select * from products where categoryid=#{id}
</select> </mapper>

启用延迟加载和按需加载

Mybatis配置文件中通过两个属性lazyLoadingEnabled和aggressiveLazyLoading来控制延迟加载和按需加载。

lazyLoadingEnabled:是否启用延迟加载,mybatis默认为false,不启用延迟加载。lazyLoadingEnabled属性控制全局是否使用延迟加载,特殊关联关系也可以通过嵌套查询中fetchType属性单独配置(fetchType属性值lazy或者eager)。

aggressiveLazyLoading:是否按需加载属性,默认值false,lazyLoadingEnabled属性启用时只要加载对象,就会加载该对象的所有属性;关闭该属性则会按需加载,即使用到某关联属性时,实时执行嵌套查询加载该属性。

SqlMapConfig.xml中修改配置,注册lazyLoadMapper.xml

<settings>
<!-- 启用延迟加载特性,不配置默认关闭该特性-->
<setting name="lazyLoadingEnabled" value="true"></setting>
<!-- 按需加载: false:使用关联属性,及时加载; true,加载对象,则加载所有属性, -->
<setting name="aggressiveLazyLoading" value="false"/>
</settings> <mappers>
<!-- 注册Mapper.xml文件 -->
<mapper resource="mapper/lazyLoadMapper.xml"></mapper>
</mappers>

运行测试

添加mapper接口

package com.sl.mapper;

import java.util.List;

import com.sl.po.Category;
import com.sl.po.Product; public interface LazyLoadMapper { Category lazyLoadTest(int id); //嵌套查询
List<Product> selectProductsByCategoryId(int cId);
}

测试方法

package com.sl.test;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat; import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test; import com.sl.mapper.LazyLoadMapper;
import com.sl.mapper.ProductMapper;
import com.sl.mapper.UnitMapper;
import com.sl.po.Category;
import com.sl.po.Product;
import com.sl.po.ProductDetailInfo;
import com.sl.po.ProductInfo;
import com.sl.po.ProductVo;
import com.sl.po.User; import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map; public class TestLazyLoadMapperClient { // 定义会话SqlSession
SqlSession session = null; @Before
public void init() throws IOException {
// 定义mabatis全局配置文件
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(inputStream);
// 根据sqlSessionFactory产生会话sqlsession
session = factory.openSession();
} // 延迟加载
@Test
public void testoneToManyTestCollectionSelect() { LazyLoadMapper mapper = session.getMapper(LazyLoadMapper.class); Category category = mapper.lazyLoadTest(1); //System.out.println(category);
System.out.println(category.getName()); if (category.getProductList().size() > 0) {
for (Product pro : category.getProductList()) {
System.out.println(pro);
}
}
// 关闭会话
session.close();
} }

运行程序查看sql执行记录:

当前配置:启用延迟加载lazyLoadingEnabled=true和按需加载aggressiveLazyLoading=false

Step1: 执行Mapper方法lazyLoadTest,实际只执行了select * from category where id=#{id}

Step2: 执行System.out.println(category.getName()),加载属性,由于启用按需加载aggressiveLazyLoading=false,name属性此前已加载好,所以此处无数据库交互

Step3: 执行category.getProductList().size(),加载属性productList,按需加载需要执行延迟加载sql脚本select * from products where categoryid=#{id},与数据库交互

将aggressiveLazyLoading属性设为为true,即:

<setting name="aggressiveLazyLoading" value="false"/>

再一下执行过程:

此时的配置:启用延迟加载lazyLoadingEnabled=true和关闭按需加载aggressiveLazyLoading=true(即加载对象则加载所有属性)

Step1: 执行Mapper方法lazyLoadTest,实际只执行了select * from category where id=#{id}

Step2: 执行System.out.println(category.getName()),访问name属性,由于启用按需加载aggressiveLazyLoading=true,关闭按需加载,则加载category对象时加载该对象的所有属性,执行延迟加载sql脚本select * from products where categoryid=#{id},与数据库交互

Step3: 执行category.getProductList().size(),访问productList属性,该 性step2已加载好,此处无需数据库交互

对比上下两个step2可以发现 aggressiveLazyLoading=true /false的区别。

最新文章

  1. Caffe学习
  2. activeamq启动失败
  3. NTP时间服务器配置与解析
  4. delphi AES encrypt
  5. Android的属性系统
  6. Java基础知识强化04:判断101~200之间有多少素数
  7. break,continue,return 区别
  8. safari 在 iPad Portrait 模式默认设置980px宽度
  9. spring学习总结(mybatis,事务,测试JUnit4,日志log4j&amp;slf4j,定时任务quartz&amp;spring-task,jetty,Restful-jersey等)
  10. 查询出各个学科的前3名的同学信息的Sql
  11. webpack+react+redux+es6开发模式---续
  12. Matlab产生TestBeach所需要的波形数据
  13. linux同步与通信
  14. 基于hashchange导航管理
  15. Win32项目生成的程序exe图标显示异常的问题
  16. Spring相关问题
  17. CF1012A Photo of The Sky
  18. 源码来袭:bind手写实现
  19. Modbus库开发笔记之四:Modbus TCP Client开发
  20. 南阳236----心急的C小加

热门文章

  1. python之selectors
  2. 一位90后程序员的自述:如何从年薪3w到30w
  3. 常用的标准SQL 语句
  4. DLL DEF文件编写方法 VC++ 调用、调试DLL的方法 显式(静态)调用、隐式(动态)调用
  5. Linux-history的用法
  6. 14.2 multiprocessing--多线程
  7. 配置p6spyLog输出sql完整日志
  8. git克隆出错 github clone Permission denied (publickey) fatal Could not read from remote repo
  9. 神级编辑器 sublime text 和 神级插件 emmet
  10. elasticsearch 5.x 系列之四(索引模板的使用,详细得不要不要的)