MyBatis的Lazy Loading可以实现延迟查询Bean里的嵌套成员类,控制lazy loading的<settings>属性有

lazyLoadingEnabled: lazy loading开关,默认为true

aggressiveLazyLoading: 侵略性 lazy loading 开关, 默认为true, 这个属性比较搞笑,如果为true则当你访问任何一个属性都会加载所有的其他lazy load属性,即使你根本没有调用哪个lazy load属性,说白了就是aggressiveLazyLoading=true,则lazy load等于没用,所以要使用lazy load还是将其设为false

一个使用lazyload的例子

ResultMap

    <!-- 使用子查询的方式查询成员变量 -->
<resultMap id="articleResultMap2" type="Article">
<id property="id" column="article_id" />
<result property="title" column="article_title" />
<result property="content" column="article_content" />
<association property="user" column="user_id" select="dao.userdao.selectUserByID"/>
</resultMap>

查询Mapper

    <!-- 测试lazy load user -->
<select id="selectArticleById2" parameterType="int" resultMap="dao.base.articleResultMap2">
SELECT * FROM article WHERE id = #{id}
</select> <select id="selectUserByID" parameterType="int" resultType="User"
flushCache="false" useCache="true" timeout="10000" statementType="PREPARED">
SELECT
*
FROM user
WHERE id = #{id}
</select>

测试代码

    public String getArticle2(Model model) {
Article article = articleDao.selectArticleById2(1);
// 如果你在这里打一个断点,你会发现还没有执行到getUser()这一句article.user已经被查询加载
// 而如果你将 getUser() 那行注释,则article.user在执行到这里也不会被加载
// 我的理解是java是编译型语言,mybatis可以根据编译好的中间码查看哪些属性被调用
// 然后在第一次执行sql的时候把后面将会调用到的延迟加载属性都提前加载了
// 另外,MyBatis有个更搞笑和骗人的地方是,如果你不在这里打断点,它lazy load的子查询就一定会出现在getUser()之后
// 而如果这里打了断点,则lazy load的子查询语句会在selectArticleById2()这个方法就出现了
System.out.println();
// 如果aggressiveLazyLoading为true,则getContent()的时候就会执行查询user的sql
// 即使你根本没有调用getUser(),也会将user属性查询出来,例如将getUser()那行注释了
System.out.println(article.getContent());
System.out.println("Lazy loading ......");
System.out.println(article.getUser());
return "index";
}

输出

DEBUG - ooo Using Connection [jdbc:mysql://127.0.0.1:3306/mybatistest?characterEncoding=utf8, UserName=root@localhost, MySQL-AB JDBC Driver]
DEBUG - ==> Preparing: SELECT * FROM article WHERE id = ?
DEBUG - ==> Parameters: 1(Integer)
DEBUG - Cache Hit Ratio [dao.userdao]: 0.0
DEBUG - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6bbe7]
DEBUG - Returning JDBC Connection to DataSource

test_content
Lazy loading ......
DEBUG - Fetching JDBC Connection from DataSource
DEBUG - JDBC Connection [jdbc:mysql://127.0.0.1:3306/mybatistest?characterEncoding=utf8, UserName=root@localhost, MySQL-AB JDBC Driver] will not be managed by Spring
DEBUG - ooo Using Connection [jdbc:mysql://127.0.0.1:3306/mybatistest?characterEncoding=utf8, UserName=root@localhost, MySQL-AB JDBC Driver]
DEBUG - ==> Preparing: SELECT * FROM user WHERE id = ?
DEBUG - ==> Parameters: 1(Integer)
DEBUG - Returning JDBC Connection to DataSource
1|test1|19|beijing

抛开上面注释中MyBatis各种奇怪的表现不说,MyBatis的Lazy Loading是基于子查询select的,也是这段

<association property="user" column="user_id" select="dao.userdao.selectUserByID"/>

这个方式最大的问题是会产生N+1问题,假设article里的user是一个List<User>:

1. 使用一条SQL语句查询Article类(the 1)

2. 使用N条SQL查询Article里的List<User>

如果我们在查询Article以后需要遍历Article的List<User>,则会触发所有user的Lazy Loading

也就是说我们也无法使用JOIN去使用Lazy Loading,从而避免n+1的问题

MyBatis Lazy Loading的更多相关文章

  1. Angular2+typescript+webpack2(支持aot, tree shaking, lazy loading)

    概述 Angular2官方推荐的应该是使用systemjs加载, 但是当我使用到它的tree shaking的时候,发现如果使用systemjs+rollup,只能打包成一个文件,然后lazy loa ...

  2. Lazyr.js – 延迟加载图片(Lazy Loading)

    Lazyr.js 是一个小的.快速的.现代的.相互间无依赖的图片延迟加载库.通过延迟加载图片,让图片出现在(或接近))视窗才加载来提高页面打开速度.这个库通过保持最少选项并最大化速度. 在线演示    ...

  3. Can you explain Lazy Loading?

    Introduction Lazy loading is a concept where we delay the loading of the object until the point wher ...

  4. [AngularJS] Lazy Loading modules with ui-router and ocLazyLoad

    We've looked at lazy loading with ocLazyLoad previously, but what if we are using ui-router and want ...

  5. [AngularJS] Lazy loading Angular modules with ocLazyLoad

    With the ocLazyLoad you can load AngularJS modules on demand. This is very handy for runtime loading ...

  6. iOS swift lazy loading

    Why bother lazy loading and purging pages, you ask? Well, in this example, it won't matter too much ...

  7. Entity Framework加载相关实体——延迟加载Lazy Loading、贪婪加载Eager Loading、显示加载Explicit Loading

    Entity Framework提供了三种加载相关实体的方法:Lazy Loading,Eager Loading和Explicit Loading.首先我们先来看一下MSDN对三种加载实体方法的定义 ...

  8. Lazy Loading | Explicit Loading | Eager Loading in EntityFramework and EntityFramework.Core

    EntityFramework Eagerly Loading Eager loading is the process whereby a query for one type of entity ...

  9. EFCore Lazy Loading + Inheritance = 干净的数据表 (二) 【献给处女座的DB First程序猿】

    前言 本篇是上一篇EFCore Lazy Loading + Inheritance = 干净的数据表 (一) [献给处女座的DB First程序猿] 前菜 的续篇.这一篇才是真的为处女座的DB Fi ...

随机推荐

  1. log4j:WARN No appenders could be found for logger (org.springframework.web.context.ContextLoader).

    一.异常描述: log4j:WARN No appenders could be found for logger (org.springframework.web.context.ContextLo ...

  2. 001 Java 深拷贝、浅拷贝及Cloneable接口

    原本写过,后来在阅读的时候,感觉自己都不是太明白了,删除后参考人家的又重新写了一份. 一:开篇 1.复制一个变量 举例是int类型. 其他其中七种原始数据类型同样适用. 原始类型:boolean,ch ...

  3. CSU训练分类

    √√第一部分 基础算法(#10023 除外) 第 1 章 贪心算法 √√#10000 「一本通 1.1 例 1」活动安排 √√#10001 「一本通 1.1 例 2」种树 √√#10002 「一本通 ...

  4. Json格式String类型字符串转为Map工具类

    package agriculture_implement.util; import com.google.gson.Gson; import com.google.gson.JsonSyntaxEx ...

  5. [python]源码-对象的创建和行为

    (明天论文就要送审了!!!距离毕业一个月!!!) 现在还记得刚开始学python时候被这种动态语言惊到的那种感觉,列表和字典对象可以随意伸缩,简直不能更帅了,但是一直不知道内部到底是怎么实现的,pyt ...

  6. opencv 加载 修改 保存 图像

    #include <opencv2/opencv.hpp> #include <iostream> using namespace cv; /* 1 加载图像 cv::imre ...

  7. [BZOJ4699]树上的最短路(最短路+线段树)

    https://www.cnblogs.com/Gloid/p/10273902.html 这篇文章已经从头到尾讲的非常清楚了,几乎没有什么需要补充的内容. 首先$O(n\log^2 n)$的做法比较 ...

  8. JavaScript数组中的22个常用方法

    数组总共有22种方法,本文将其分为对象继承方法.数组转换方法.栈和队列方法.数组排序方法.数组拼接方法.创建子数组方法.数组删改方法.数组位置方法.数组归并方法和数组迭代方法共10类来进行详细介绍. ...

  9. 解决CIFilter滤镜后图片大小和方向发生变化

    调用contextWithOptions:和createCGImage: fromRect:方法创建CIContext.与以往不同的地方是CIImage没有frame与bounds属性:只有exten ...

  10. PostgreSQL控制台以竖行显示

    \x select * from user; 这个和MySQL的有点区别,在查询之前使用\x进行显示的开启 注意:只需要用一次即可,以后的查询都是以竖行进行显示.