Mybatis学习系列(六)延迟加载
延迟加载其实就是将数据加载时机推迟,比如推迟嵌套查询的执行时机。在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的区别。
Mybatis学习系列(六)延迟加载的更多相关文章
- MyBatis学习系列三——结合Spring
目录 MyBatis学习系列一之环境搭建 MyBatis学习系列二——增删改查 MyBatis学习系列三——结合Spring MyBatis在项目中应用一般都要结合Spring,这一章主要把MyBat ...
- MyBatis学习系列二——增删改查
目录 MyBatis学习系列一之环境搭建 MyBatis学习系列二——增删改查 MyBatis学习系列三——结合Spring 数据库的经典操作:增删改查. 在这一章我们主要说明一下简单的查询和增删改, ...
- MyBatis学习系列一之环境搭建
目录 MyBatis学习系列一之环境搭建 MyBatis学习系列二——增删改查 MyBatis学习系列三——结合Spring 学习一个新的知识,首先做一个简单的例子使用一下,然后再逐步深入.MyBat ...
- mybatis学习记录七——延迟加载
14 延迟加载 14.1 什么是延迟加载 resultMap可以实现高级映射(使用association.collection实现一对一及一对多映射),association.co ...
- mybatis学习记录六——一对一、一对多和多对多查询
9 订单商品数据模型 9.1 数据模型分析思路 1.每张表记录的数据内容 分模块对每张表记录的内容进行熟悉,相当 于你学习系统 需求(功能)的过程. 2.每张表重要的字段设置 非空 ...
- mybatis学习系列二
1 参数处理(封装map过程)(23) 1.1)F5进入断点:Employee employee1=mapper.selectEmployeeByMap(map); 1.2)进入MapperProxy ...
- mybatis学习系列一
1引入dtd约束(6) Mybatis git地址:https://github.com/mybatis/mybatis-3/wiki/Maven 指导手册:http://www.mybatis.or ...
- MyBatis学习 之 六、insert操作返回主键
数据库操作怎能少了INSERT操作呢?下面记录MyBatis关于INSERT操作的笔记,以便日后查阅. 二. insert元素 属性详解 其属性如下: parameterType ,入参的全 ...
- MyBatis学习总结(六)——调用存储过程(转载)
本文转载自:http://www.cnblogs.com/jpf-java/p/6013518.html 一.提出需求 查询得到男性或女性的数量, 如果传入的是0就女性否则是男性 二.准备数据库表和存 ...
随机推荐
- layDate 闪现 循环一个以上会闪现
一个render一次渲染一个日期组件,这个是内置的,所以需要循环绑定, 又不能确定页面有多少个,还好layDate 提供了内置方法, //同时绑定多个 lay('.test-item').each(f ...
- linux运维、架构之路-shell编程(一)
一.shell编程入门必备基础 1.vim编辑器的命令,vimrc设置 2.150个linux基础命令 3.linux中基础的系统服务crond,ssh网络服务,nfs,rsync,inotify,l ...
- linux下的shadow文件解释
/etc/shadow //用户密码文件登录名:加密口令:最后一次修改时间:最小时间间隔:最大时间间隔:警告时间:不活动时间:失效时间:标志 root:$1$202cb962ac59075b964b0 ...
- Ubuntu 16.04 swoole扩展安装注意!!!
前言:目前很多项目估计常常会用到swoole扩展,如个人使用Ubuntu虚拟机安装扩展,这里总结一下遇到的问题: 一.先保证服务器时间同步当前地区时间,如北京时间: 1.设定时区 如:设定时区:dpk ...
- JavaSE 第二次学习随笔(五)
/* * 中文乱码出现的情况研究 * 注意点:乱码解决的办法是再编码再解码 * 但是如果是编码出错了,无法解决.如果是解码出错了,可以利用再编码再解码 * * * 编码 解码 结果 * GBK utf ...
- Source Insight的使用
1. source insight查看函数的上一级调用的位置(函数) --> 鼠标放在函数上,右键 选择 Jump To caller,就可以看到有哪些函数调用它了:
- ruby OpenURI模块使用
OpenURI is an easy-to-use wrapper for Net::HTTP, Net::HTTPS and Net::FTP(OpenURI支持重定向) 像打开普通文件那样打开ht ...
- python 面向对象 (多态)
什么是多态?多态就像是人有多种心情,场景不一样心情就会不一样. class Dog: def print_self(self): print('this is dog') class Hsq(Dog) ...
- vue---day04
1. Node.js 1.1 介绍: - Node.js 是一个JavaScript运行环境,实质上是对Chrome V8引擎的封装. - Node.js 不是一个 JavaScript 框架,不同于 ...
- 「LibreOJ#516」DP 一般看规律
首先对于序列上一点,它对答案的贡献只有与它的前驱和后驱(前提颜色相同)构成的点对, 于是想到用set维护每个颜色,修改操作就是将2个set暴力合并(小的向大的合并),每次插入时更新答案即可 颜色数要离 ...