文章目录
MyBatis执行体系
MyBatis
是基于JDBC
的sql
执行框架,他工作在DAO
层。- 如果单从写法上看:
- 加载配置文件
- 获取
SqlSesionFactory
- 获取
SqlSession
- 操作
Mapper
接口
- 深入
SQL
执行过程,分为四个模块,如下:
(1)动态代理(MapperProxy)
- 通过JDK动态代理,帮mapper接口生成代理实现类
(2)SQL会话(SqlSession)
门面模式:(提供一个统一的门面接口API,使得系统更容易使用)
SqlSession
采用门面模式,只提供API
,例如基本的API(增,删,改,查)和辅助API(提交,关闭会话),但他不负责这些API的实现。具体的处理交给执行器(Executor)。- 会话方式:降低调用的复杂性。
(3)执行器Executor
Executor
提供的基本功能:改
,查
,维护缓存
- 在
JDBC
的标准API
中,其实只有改和查,是没有增和删的,并且增删最终都可以归结于改和查。 - 改查,又会涉及到另一个东西:
缓存
,对于查而言,可以从缓存中查,提高效率,对于改而言,数据库变更了,那么缓存也要做相应变动。
- 辅助API:
提交增删改
,关闭执行器
,批处理刷新
- 三种执行器:
1. 简单执行器(SimpleExecutor)
- 无论SQL是否一样,每次执行语句都会进行
预编译
!!!
- 如果进行多次操作,那么就会进行多次预编译,影响性能,我们可以对
预处理对象
进行重用,就要用到可重用执行器
2.可重用执行器(ReuseExecutor)
- 重用预处理对象
- 如果相同的
sql
语句非常多的情况下,就可以使用可重用执行器,如果有大量的修改操作,就可以用到批处理执行器。
3. 批处理执行器(BatchExecutor)
- 当有大量数据操作,比如说10000条语句,那么一条一条就会拖累速度,可以用批处理执行器,一次执行100条,或者更多。
- 批处理执行器只针对修改操作,如果是查询操作,那么批处理执行器和简单执行器是没有任何区别的。
- 注意: 批处理操作必需手动刷新,就相当于装填弹药之后,手动发射一样。
executor.doFlushStatements(false);
执行器抽象类(BaseExecutor)
- 将三种执行器重复的操作抽象出来,专门用来实现缓存相关的逻辑。
- 重复的操作包括:一级缓存,获取连接。
- 在
BaseExecutor
中实现两个方法:query()
和update()
,而这两个方法有对应着子类具体实现doquery()
和doupdate()
,就在三种执行器中。
二级缓存(CachingExecutor)
- 二级缓存与一级缓存的区别:
- 二级缓存只有设置了才会有,没设置就没有。
- 一级缓存:当执行完查询操作后,缓存中就立马有数据了,二级缓存:提交之后,二级缓存才会有数据。
- 先走二级缓存,再走一级缓存
- 如果将二级缓存写进
BaseExecutor
中,就会造成这个抽象类职责不专一,在mybatis
中的写法是,再声明一个类CachingExecutor
,采用装饰者模式,在BaseExecutor
功能的基础上,添加二级缓存的功能。这样即可以将职责分离开来,也不会破坏原有的继承结构。 - 装饰者模式:在不改变原有结构和继承的情况下,通过
包装原对象
去扩展一个新功能。 - 这里的
delegate
就是被包装的对象。当执行完二级缓存相关的逻辑之后,就交给下一个执行器,继续处理数据库相关的逻辑。
总结流程
- 会话式流程。
- 先调用
SqlSession
中的API
方法 - 转化为
CachingExecutor
,执行二级缓存相关逻辑 - 再到
BaseExecutor
中执行query()
或者update()
方法 - 交给具体的执行器,实现
doquery()
或者doupdate()
。 - 完成操作。