一. MyBatis 执行流程
(1)在 Spring 中,我们需要手写配置 mybatis-config.xml 文件;在 SpringBoot 中,数据库配置 以及 MyBatis配置 等都集中在 application.yml/properties 当中。
(2)SqlSessionFactory 整个 Spring 项目只有一个;SqlSession 每一次操作请求都会生成一个,一对一SQL语句。
(3)Executor 封装了 JDBC,也负责维护缓存。
(4)最后,MappedStatement 还要收集一些信息,例如:哪一个Mapper.xml文件?SQL 的 id 是什么?SQL 语句内容?resultMap 是怎么定义的? 等等…
(5)现在我们获取了完整的信息,SQL可以准备执行了,可以真正的操作数据库!
(6)SQL执行的时候 当然要带上参数,所以过程中还涉及输入参数、输出结果 的 类型转换 问题。
二. MyBatis 延迟加载
Mybatis 支持延迟加载,但是默认关闭!
1. 技术背景
我们在写 resultMap 的时候会用到 association 和 collection 标签做多表查询,但是这些关联信息时常不需要,每次都查询出来 非常耗时。
延迟加载就是为了解决这一问题 —— 只有当业务代码中 需要 获取关联信息的时候,mybatis 才去执行 目标SQL,获取关联数据。
2. 使用方法
- 局部开启:在目标 association / collection 标签上添加属性
fetchType="lazy"
; - 全局开启:在配置文件 mybatis-config.xml 中添加一条
<setting name="lazyLoadingEnabled" value="true" />
3. 延迟原理(代理对象)
核心:CGLIB 为 使用了延迟加载的 对象A 创建 代理对象 ❗
每当 对象A 调用 延迟处理的那部分 关联数据,它的 代理对象 都会 率先 进入 invoke方法,检查关联数据是否为空!
如果为空,那么执行相关SQL,把结果封装回对象A的属性当中;不为空就直接返回已存在的数据。
三. MyBatis 缓存
MyBatis 的缓存都是基于 PerpetualCache 的 HashMap 本地缓存。
注意:一级缓存默认开启,二级缓存默认关闭。
1. 一级缓存
一级缓存 的作用域为 SqlSession,即 单条select语句。
当 SqlSession 进行 flush 或 close(提交 / 关闭) 之后,该 SqlSession 中的所有缓存将从一级缓存中清空,进入二级缓存,这也是 二级缓存 添加 / 更新 的方式。
2. 二级缓存
二级缓存 的作用域为 namespace 和 mapper 的作用域,即一整个 <mapper namespace="package_name.mapper.MapperName">...</mapper>
。显然,二级缓存的覆盖面是非常广的,通常包含了 一块业务逻辑。
当 二级缓存 的作用域中 执行了一条 insert / update / delete 操作之后,该二级缓存就将被 全部清空!
⭐ MyBatis的二级缓存 和 Redis缓存操作 比较相似:
① 读操作【读取数据、更新缓存】
② 写操作【更新数据、删除缓存】
👉 【面试资料】Redis篇 之 双写一致…
二级缓存 开启方法:
- 在 配置文件mybatis-config.xml 中 添加一条
<setting name="cacheEnabled" value="true />
; - 在对应的 Mapper.xml 映射文件 中加上一条
<cache/>
。