MyBatis:lazy loading
懒加载的原理
mybatis 会循环处理结果集中返回的每行数据的,在处理之前首先会通过反射调用构造方法来创建 result 对象,结果集中的一行数据最终会映射为一个 result 对象(严格的来说是不对的,结果集中的一行数据在多表连接的情况下可能会映射为多个 result 对象,结果集中的一行数据在多表连接一对多的情况下结果集中的多行数据可能映射一个 result 对象,简单的单表查询结果集中的一行数据映射为一个 result 对象)。
其实在调用构造方法创建 result 对象的时候,构造方法还可能会有参数,需要先把结果集中的参数都提取出来,传给相应的构造方法通过反射创建对象。
mybatis 其实第一步是解析配置文件,把配置文件映射为 mybatis 的 Configuration 类,把配置文件的 xml 属性都映射为 Java 对象中的属性值。xml mapper 文件的处理比较复杂,< resultMap/> 标签映射为 ResultMap 对象, 标签中的< id/> 、< result/>、< association/> 等映射为 ResultMapping 对象。
其实要讲 mybatis 的实现过程,涉及到的点太多了,没法在一篇博客中讲。在这里,我只简单的讲一下原理。
接着再讲创建好 result 对象之后,mybatis 会循环 resultMappings(标签中的每个子标签都映射为一个 resultMapping,这些 resultMapping 组成了一个集合就是 resultMappings)集合,看有没有需要懒加载的属性,如果有的话,则会为这个 result 对象创建一个代理对象。
什么情况下才会出现需要懒加载的属性呢?只有 < association property=”author” column=”author_id” select=”selectAuthor” fetchType=”lazy”/>
和 < collection property=”xxx” column=”xxx” select=”xxxx” fetchType=”lazy”/> 作为一个子标签出现在 < resultMap/> 标签(也不一定只是 < resultMap/> 标签,< collection/> 等标签事实上也算是一个 < resultMap/> 标签)之内才会出现需要懒加载的属性。select 属性和 fetchType=”lazy” 必须同时出现在 < collection/> 或 < association/> 属性中才需要懒加载,select 表示的是嵌套查询语句的 id ,fetchType=”lazy” 表示的是懒加载。
再接着讲 result 对象的代理对象,代理类是由 javassist 框架在运行时创建和加载的,这个代理类继承自 result 对象所属的类,以上面的例子为例,这个代理类继承自 Blog 类。
对于这个代理类的详细讲解在我的博客深入理解 Java 动态代理中有很详细的介绍,在这里我再简单的介绍下。
这个代理类继承了 result 对象所属的类(被代理类)并重写了被代理类的所有的方法,所以在代理对象上调用懒加载属性的 get 方法(getAuthor())时会触发懒加载动作,mybatis 这时就能发现需要去懒加载一个属性,然后去加载这个属性。
其实,有几个方法都可以触发懒加载的操作,比如调用懒加载的 get/set 方法(确实调用 set 方法时也会触发懒加载操作)还有调用 clone()、equals()、hashCode()、toString()方法也会触发懒加载操作,如果代理对象有多个懒加载属性,则调用后面的这四个方法时会同时触发加载所有的懒加载属性。
懒加载操作只会触发一次,下次再调用这些方法时不会再次触发懒加载操作的。
懒加载其实又是一次查询操作,懒加载查询需要传递一些参数,还有一些其他条件。这些待传递的属性、参数、查询所需的 sql 语句等相关的条件都已经封装到了代理对象内部,这些条件封装在一个 Map 中,键是懒加载查询的属性名称,值是查询该属性所需的条件,包括参数、sql 语句等。懒加载完一个属性之后会把这个属性从 Map 中移除,所以再次出发懒加载操作时 mybatis 就知道该属性已经被被加载过了,不会重复加载。
懒加载也是一个挺复杂的过程,我在上面的讲解中省略了很多,要全部讲出来涉及的东西太多。
我再总结一下,懒加载功能使用了代理对象,所以在调用懒加载属性的 get/set 方法(或者是其他触发懒加载操作的方法)时 mybatis 才能知道这时候应该去加载懒加载属性。
ORM 框架hibernate 也是支持lazy 加载的,相信原理也是类似的。
MyBatis:lazy loading的更多相关文章
- Entity Framework Tutorial Basics(37):Lazy Loading
Lazy Loading: One of the important functions of Entity Framework is lazy loading. Lazy loading means ...
- MyBatis Lazy Loading
MyBatis的Lazy Loading可以实现延迟查询Bean里的嵌套成员类,控制lazy loading的<settings>属性有 lazyLoadingEnabled: lazy ...
- Entity Framework加载相关实体——延迟加载Lazy Loading、贪婪加载Eager Loading、显示加载Explicit Loading
Entity Framework提供了三种加载相关实体的方法:Lazy Loading,Eager Loading和Explicit Loading.首先我们先来看一下MSDN对三种加载实体方法的定义 ...
- 001_Chrome 76支持原生HTML 图片懒加载Lazy loading
Table Of Content 什么是懒加载? 语法参数及使用方式? 有哪些特点? 与js有关的实践 什么是懒加载? 技术背景 Web应用需要经常向后台服务器请求资源(通过查询数据库,是非常耗时耗资 ...
- 你所不知道的库存超限做法 服务器一般达到多少qps比较好[转] JAVA格物致知基础篇:你所不知道的返回码 深入了解EntityFramework Core 2.1延迟加载(Lazy Loading) EntityFramework 6.x和EntityFramework Core关系映射中导航属性必须是public? 藏在正则表达式里的陷阱 两道面试题,带你解析Java类加载机制
你所不知道的库存超限做法 在互联网企业中,限购的做法,多种多样,有的别出心裁,有的因循守旧,但是种种做法皆想达到的目的,无外乎几种,商品卖的完,系统抗的住,库存不超限.虽然短短数语,却有着说不完,道不 ...
- Lazyr.js – 延迟加载图片(Lazy Loading)
Lazyr.js 是一个小的.快速的.现代的.相互间无依赖的图片延迟加载库.通过延迟加载图片,让图片出现在(或接近))视窗才加载来提高页面打开速度.这个库通过保持最少选项并最大化速度. 在线演示 ...
- Can you explain Lazy Loading?
Introduction Lazy loading is a concept where we delay the loading of the object until the point wher ...
- EFCore Lazy Loading + Inheritance = 干净的数据表 (二) 【献给处女座的DB First程序猿】
前言 本篇是上一篇EFCore Lazy Loading + Inheritance = 干净的数据表 (一) [献给处女座的DB First程序猿] 前菜 的续篇.这一篇才是真的为处女座的DB Fi ...
- EFCore Lazy Loading + Inheritance = 干净的数据表 (一) 【献给处女座的DB First程序猿】
前言 α角 与 β角 关于α角 与 β角的介绍,请见上文 如何用EFCore Lazy Loading实现Entity Split. 本篇会继续有关于β角的彩蛋在等着大家去发掘./斜眼笑 其他 本篇的 ...
随机推荐
- Python返回Json格式定义的例子
{ "code": 0, // code为0表示成功,否则为1 "message": null, "data": { "syscp ...
- Shiro SpringMVC 非maven HelloWorld
项目用到Shiro就从网上找一些案例看看吧,结果看了很多都是maven的,没有办法就自己弄了一个.废话不多说,原理自己找开始上菜. 配置web.xml <?xml version="1 ...
- [动态规划]P1004 方格取数
---恢复内容开始--- 题目描述 设有N*N的方格图(N<=9),我们将其中的某些方格中填入正整数,而其他的方格中则放 人数字0.如下图所示(见样例): A 0 0 0 0 0 0 0 0 0 ...
- oracle 物化视图 job
在oracle数据库里边,创建物化视图之后,系统在DBMS_jobs文件夹下,会自动创建相应的job,右键执行job的时候报错如下: 问题:ORA-12012: 自动执行作业 198 出错 ORA-1 ...
- 12. ZooKeeper配额和认证
ZooKeeper具有与其数据模型相关的可配置配额(quota). 可以设置znode上的配额限制和存储的数据量.如果ZooKeeper命名空间中的一个子树超出与其关联的配额,ZooKeeper会在日 ...
- PHP yield 分析,以及协程的实现,超详细版(上)
参考资料 http://www.laruence.com/2015/05/28/3038.html http://php.net/manual/zh/class.generator.php http: ...
- 罗培羽—C语言简单游戏编程教学
编写许多软件都需要有菜单,那么如果我们使用tc之类的软件来编译程序的话,我们该怎么编写菜单呢?让我们一起来试试吧!第一步:简单例子 我们先来写个最简单的例子:#include<std ...
- [Machine Learning]学习笔记-线性回归
模型 假定有i组输入输出数据.输入变量可以用\(x^i\)表示,输出变量可以用\(y^i\)表示,一对\(\{x^i,y^i\}\)名为训练样本(training example),它们的集合则名为训 ...
- iOS 中 .a 和 .framework 静态库的创建与 .bundle 资源包的使用
iOS 中 .a 和 .framework 静态库的创建与 .bundle 资源包的使用 前言 开发中经常使用三方库去实现某特定功能,而这些三方库通常又分为开源库和闭源库.开源库可以直接拿到源码,和自 ...
- nginx的基础应用
nginx的基础应用 一.简介 今天我们将介绍一些nginx的简单应用,启动.停止nginx,重载nginx的配置,nginx配置文件的格式,如何配置nginx服务静态资源,如何配置nginx作为反向 ...