作者源码阅读笔记主要采用金山云文档记录的,所有的交互图和代码阅读笔记都是记录在云文档里面,本平台的文档编辑实在不方便,会导致我梳理的交互图和文档失去原来的格式,所以整理在文档里面,供大家阅读交流.
【金山文档 | WPS云文档】 SqlSession 会话源码和Executor SQL操作执行器源码
SqlSession
是框架与数据库交互的核心接口。
核心功能
- SQL 操作执行
提供 insert()
、update()
、delete()
、select()
等方法直接执行 SQL 语句,支持参数绑定与结果映射
- 事务管理
通过 commit()
和 rollback()
控制事务提交与回滚,需手动调用(非自动提交模式)
- Mapper 接口代理
通过 getMapper(Class<T> type)
动态生成 Mapper 接口实现类,实现面向对象式数据库操作
- 缓存管理
默认启用一级缓存(会话级),缓存相同 SQL 查询结果,通过 clearCache()
可手动清空。
Executor
包是 MyBatis 执行 SQL 操作的核心引擎,位于 org.apache.ibatis.executor
包下,负责协调 SQL 执行全流程(包括缓存管理、事务控制、参数处理、结果映射等)
Executor
包是 MyBatis 的 SQL 执行中枢,通过多态实现支持基础操作、缓存优化、批量处理等场景,并协调四大组件完成从 SQL 解析到结果映射的全链路操作
核心接口与实现
Executor
接口
定义 SQL 执行的标准方法:
public interface Executor {
int update(MappedStatement ms, Object parameter); // 执行更新操作
<E> List<E> query(...); // 执行查询操作
void commit(boolean required); // 提交事务
void rollback(boolean required); // 回滚事务
CacheKey createCacheKey(...); // 创建缓存键
boolean isCached(MappedStatement ms, CacheKey key); // 检查缓存
}
基础实现类(BaseExecutor
子类)
|---------------------|-----------------------------------------------------------|-------------|
| 类型 | 特点 | 适用场景 |
| SimpleExecutor | 默认执行器,每次执行创建新 Statement
,执行后立即关闭 | 常规单条 SQL 操作 |
| ReuseExecutor | 复用 Statement
对象,缓存相同 SQL 的 Statement
以减少重复编译开销 | 高频重复 SQL |
| BatchExecutor | 批量执行 SQL,通过 addBatch()
缓存操作,调用 flushStatements()
统一提交 | 批量插入/更新 |
增强实现类 CachingExecutor
- 二级缓存代理:装饰器模式,在基础执行器外层添加二级缓存逻辑
- 工作流程:
- 优先查询二级缓存(
MappedStatement
级别); - 缓存未命中时委托底层执行器(如
SimpleExecutor
)查询数据库
协作组件
Executor 通过组合模式调用其他三大组件:
|------------------------|--------------------------------|-------------------------|
| 组件 | 职责 | 依赖关系 |
| StatementHandler | 处理 Statement
创建与参数绑定 | Executor 调用其执行 SQL |
| ParameterHandler | 转换参数类型并填充到 PreparedStatement
| 被 StatementHandler
调用 |
| ResultSetHandler | 封装结果集到 Java 对象 | 被 StatementHandler
调用 |
相关重要类介绍说明
SqlSessionManager 类
|-------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----|
| 名称 | 描述 | 默认值 |
| sqlSessionFactory | 核心作用 * 作为底层工厂实例,用于创建原生 SqlSession
对象(通过 openSession()
方法) * 代理模式下(调用 startManagedSession()
后),通过动态代理自动管理会话生命周期,此时 sqlSessionFactory
负责在后台创建线程绑定的 SqlSession
| |
| sqlSessionProxy | sqlSessionProxy
字段是一个关键动态代理对象 #### 核心功能 * 动态代理拦截 作为 SqlSession
的代理实例,拦截所有 Mapper 方法调用,并路由到当前线程绑定的 SqlSession
或新建会话 通过 InvocationHandler
实现方法调用的统一处理(如事务提交、异常回滚) * 线程安全会话管理 优先从 ThreadLocal
(localSqlSession
)获取会话,避免重复创建,确保线程隔离 若未绑定会话(未调用 startManagedSession()
),则临时创建并自动关闭会话(非托管模式) | |
| localSqlSession | localSqlSession
字段是一个关键线程安全控制组件 #### 核心作用 * 线程隔离存储 通过 ThreadLocal<SqlSession>
实现线程绑定的会话管理,确保每个线程操作独立的 SqlSession
实例 避免多线程环境下会话冲突(如事务交叉) * 托管模式标志 当调用 startManagedSession()
后,新创建的 SqlSession
会存入此字段,标记当前线程进入托管模式 未调用时字段值为 null
,代理对象每次临时创建新会话 | |
-
sqlSessionProxy代理对象创建:
this.sqlSessionProxy = (SqlSession) Proxy.newProxyInstance(SqlSessionFactory.class.getClassLoader(),
new Class[] { SqlSession.class }, new SqlSessionInterceptor()); -
SqlSessionInterceptor 拦截器
每次调用代理对象 sqlSessionProxy 方法都会去执行invoke方法
private class SqlSessionInterceptor implements InvocationHandler {
public SqlSessionInterceptor() {
// Prevent Synthetic Access
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
final SqlSession sqlSession = SqlSessionManager.this.localSqlSession.get();
if (sqlSession != null) {
try {
return method.invoke(sqlSession, args);
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
}
try (SqlSession autoSqlSession = openSession()) {
try {
final Object result = method.invoke(autoSqlSession, args);
autoSqlSession.commit();
return result;
} catch (Throwable t) {
autoSqlSession.rollback();
throw ExceptionUtil.unwrapThrowable(t);
}
}
}
}
SqlSessionFactory sqlSession 工厂类
负责创建和管理 SqlSession
实例
|---------------|--------|-----|
| 名称 | 描述 | 默认值 |
| configuration | 全局配置实例 | |
DefaultSqlSession 默认会话类
|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------|
| 名称 | 描述 | 默认值 |
| configuration | 全局配置实例 | |
| executor | sql执行器 | |
| autoCommit | 控制事务提交机制的核心参数 | 默认值为 false
(需手动提交事务) |
| dirty | 用于标记当前会话是否存在未提交数据变更的关键状态标识 #### 核心功能 * 更新操作触发:执行 insert/update/delete****操作时自动置为 true**,表示有未提交的修改** * 事务提交后重置:调用 commit()**或 rollback()后重置为 false,标识数据已同步 * 连接关闭兜底处理:若未提交事务时关闭会话(** close()****),自动触发回滚并重置 dirty**** | |
| cursorList | 用于管理流式查询游标的关键资源集合 | |
所有具体执行器父类 BaseExecutor抽象类
|---------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----|
| 名称 | 描述 | 默认值 |
| transaction | 管理数据库事务的核心组件 | |
| wrapper | BaseExecutor
的 wrapper
字段是其自身实例的引用,核心作用在于实现装饰器模式,为执行器提供动态扩展能力。 若未配置装饰器,wrapper
指向自身,直接执行 BaseExecutor
的逻辑;若配置装饰器(如 CachingExecutor
),则调用装饰器的增强方法 | |
| deferredLoads | BaseExecutor
的 deferredLoads 字段是实现 MyBatis 延迟加载(懒加载) 机制的核心组件,用于管理需要延迟加载的关联对象 deferredLoads
字段通过封装延迟加载任务队列,实现了 MyBatis 高效的懒加载机制,是优化复杂对象查询性能的关键组件 | |
| localCache | BaseExecutor
的 localCache 字段是 MyBatis 一级缓存(本地缓存) 的核心实现。 localCache
是 MyBatis 一级缓存的核心载体,通过会话级缓存优化重复查询性能。 #### 典型问题与使用建议 1. 脏读风险 对于不同的sqlsession A与B,A做update操作,只能刷新A自己的一级缓存,无法刷新B的一级缓存。所以如果A与B操作同一条记录,就会有脏读。 SqlSessionB第一查询时进行了缓存,第二次查询时从缓存获取数据(脏数据),之后进行逻辑处理以及更新 | |
| localOutputParameterCache | BaseExecutor
的 localOutputParameterCache 字段是 MyBatis 用于存储过程输出参数缓存的核心组件 | |
| configuration | 全局配置 | |
| queryStack | 控制嵌套查询与延迟加载的关键计数器 #### 典型场景示例 1. 嵌套查询: 主查询 User
触发关联对象 Order
的懒加载时,queryStack
会从 0→1→0 变化,确保关联查询仅在顶层触发 1. 循环依赖规避: 若 User
和 Order
互相引用,queryStack
机制会阻断循环加载,避免栈溢出 | |
| closed | 标识执行器(Executor)是否已被关闭的关键状态标记 | |
基于SQL语句复用的执行器 ReuseExecutor 类
通过内部维护的 Map<String, Statement>
缓存(键为 SQL 语句,值为对应的 Statement
对象),避免相同 SQL 的重复编译与创建开销。适用于高频执行相同结构 SQL(如循环中参数化查询)的场景
|--------------|---------------------------------------------------------------------------------------------|-----|
| 名称 | 描述 | 默认值 |
| statementMap | statementMap 字段是其实现 Statement****对象复用的核心缓存容器,通过减少 JDBC 语句编译与创建开销提升高频重复 SQL 的执行效率 | |
批量操作执行器 BatchExecutor 类
BatchExecutor
是 MyBatis 中专为批量数据库操作优化的执行器实现,通过延迟执行与批量提交机制显著提升大批量数据操作的性能
|------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----|
| 名称 | 描述 | 默认值 |
| statementList | statementList 字段是其实现批量操作的核心数据结构,用于缓存待执行的 Statement
对象以实现批量提交优化 #### 工作流程 1. 缓存阶段 * 执行增删改操作时,将相同 SQL 结构的 Statement
存入 statementList
,并通过 addBatch()
添加参数 * 若 SQL 结构变化(如切换表或操作类型),则创建新 Statement
并加入列表 1. 批量提交 * 调用 flushStatements()
或事务提交时,遍历 statementList
执行批量操作 * 提交后清空列表并关闭所有 Statement
| |
| batchResultList | batchResultList 字段是其实现批量操作结果跟踪的核心数据结构,用于记录每条批量操作的执行状态和参数信息 | |
| currentSql | currentSql 字段是其实现 SQL 批量优化的关键标识,用于动态跟踪当前正在处理的 SQL 语句以实现批量操作的智能分组 | |
| currentStatement | currentStatement 字段是用于跟踪当前批量操作关联的 MappedStatement
对象的核心标识,其设计旨在实现 SQL 执行的上下文一致性管理 | |
二级缓存执行器 CachingExecutor 类
CachingExecutor是一个基于装饰者模式实现的执行器类,主要用于增强二级缓存功能
|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----|
| 名称 | 描述 | 默认值 |
| delegate | delegate
字段是其实现装饰器模式的关键组件,用于承载实际的数据库操作执行器 delegate
是 CachingExecutor
连接具体执行器的桥梁,使缓存功能可叠加于不同执行策略之上,体现了装饰器模式在 MyBatis 中的灵活应用 | |
| tcm | tcm
字段是实现二级缓存事务性提交的核心组件,全称为 TransactionalCacheManager
#### 核心职责 1. 事务性缓存管理 确保二级缓存的数据仅在事务成功提交后生效,避免脏读问题。当执行写操作(如 update)时,缓存变更不会立即同步到二级缓存,而是暂存在 TransactionalCache
中,直至事务提交 1. 多命名空间协调 管理多个映射语句(MappedStatement
)对应的 TransactionalCache
实例,维护不同 Cache
对象的隔离性与一致性 这一设计解决了多 SqlSession
并发场景下二级缓存的数据一致性问题。 | |
TransactionalCacheManager 二级缓存事务管理器
MyBatis 的 TransactionalCacheManager
是二级缓存事务管理的核心组件,主要负责在事务提交时协调多个 TransactionalCache
的缓存同步操作
核心职责
- 事务性缓存控制
管理多个 TransactionalCache
实例,确保二级缓存的更新仅在事务提交后生效,避免事务未提交时其他会话读取到脏数据
- 多缓存空间隔离
通过 Map<String, TransactionalCache>
结构维护不同命名空间(namespace
)的缓存实例,实现缓存区域的隔离与协同
|---------------------|-------------------------------------------------------------------------------------------|----------------------------------|
| 名称 | 描述 | 默认值 |
| transactionalCaches | 维护底层真实缓存(如 PerpetualCache
)与事务缓存代理(TransactionalCache
)的映射关系,确保每个 Cache
对象都有独立的事务暂存区 | Map<Cache, TransactionalCache> |
TransactionalCache 二级事务缓存类
TransactionalCache
是二级缓存事务管理的核心代理类,负责在事务提交前拦截缓存操作,确保数据一致性
核心职责
- 事务暂存区
代理真实的 Cache
对象(如 PerpetualCache
),在事务提交前将写操作(putObject
)暂存于内存,避免未提交事务污染二级缓存
- 脏数据隔离
通过 entriesToAddOnCommit
(待提交数据)和 entriesMissedInCache
(未命中记录)两个集合,隔离事务内外的缓存状态
|----------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------|
| 名称 | 描述 | 默认值 |
| delegate | delegate
字段是二级缓存实现的核心代理对象,其设计体现了装饰器模式的应用 delegate
字段是 MyBatis 二级缓存事务机制与底层存储的桥梁,其设计完美体现了装饰器模式 和单一职责原则 核心职责 1、真实缓存代理 :持有底层缓存实现(如 PerpetualCache
),所有缓存操作最终委托给该对象执行 2、功能扩展基础 :通过装饰器模式(如 LruCache
、ScheduledCache
)对基础缓存增强,而 delegate
是装饰链的最终执行者 | |
| clearOnCommit | 用于控制事务提交时是否清空底层缓存 | 默认值为 false
,可通过特定操作(如更新语句)动态修改状态 |
| entriesToAddOnCommit | entriesToAddOnCommit
字段是二级缓存事务管理的核心数据结构,其设计实现了事务隔离性 与批量提交优化 核心职责 * 事务暂存区 :临时存储事务内所有 putObject
操作的数据,直到事务提交时批量写入底层缓存(delegate
) * 脏写隔离:避免未提交事务的中间状态污染二级缓存,确保其他会话读取的数据一致性 | Map<Object, Object> entriesToAddOnCommit |
| entriesMissedInCache | 用于追踪二级缓存未命中记录的关键字段,其设计目的主要在于优化并发场景下的缓存一致性与阻塞控制; 记录事务执行过程中缓存查询未命中的键(Key) 该字段是 MyBatis 二级缓存应对高并发穿透问题的核心设计组件之一。 | Set<Object> entriesMissedInCache |
CacheKey 缓存key类
缓存key生成逻辑代码:
@Override
public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
if (closed) {
throw new ExecutorException("Executor was closed.");
}
CacheKey cacheKey = new CacheKey();
cacheKey.update(ms.getId());
cacheKey.update(rowBounds.getOffset());
cacheKey.update(rowBounds.getLimit());
cacheKey.update(boundSql.getSql());
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
TypeHandlerRegistry typeHandlerRegistry = ms.getConfiguration().getTypeHandlerRegistry();
// mimic DefaultParameterHandler logic
MetaObject metaObject = null;
for (ParameterMapping parameterMapping : parameterMappings) {
if (parameterMapping.getMode() != ParameterMode.OUT) {
Object value;
String propertyName = parameterMapping.getProperty();
if (parameterMapping.hasValue()) {
value = parameterMapping.getValue();
} else if (boundSql.hasAdditionalParameter(propertyName)) {
value = boundSql.getAdditionalParameter(propertyName);
} else if (parameterObject == null) {
value = null;
} else {
ParamNameResolver paramNameResolver = ms.getParamNameResolver();
if (paramNameResolver != null
&& typeHandlerRegistry.hasTypeHandler(paramNameResolver.getType(paramNameResolver.getNames()[0]))
|| typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
value = parameterObject;
} else {
if (metaObject == null) {
metaObject = configuration.newMetaObject(parameterObject);
}
value = metaObject.getValue(propertyName);
}
}
cacheKey.update(value);
}
}
if (configuration.getEnvironment() != null) {
// issue #176
cacheKey.update(configuration.getEnvironment().getId());
}
return cacheKey;
}
影响key生成的因素:
- Mapper的Id,即Mapper命名空间与<select|update|insert|delete>标签的Id组成的全局限定名
- 查询结果的偏移量及查询的条数
- 具体的SQL语句及SQL语句中需要传递的所有参数
- MyBatis主配置文件中,通过<environment>标签配置的环境信息对应的Id属性值
相关流程图整理
元数据简略图

执行流程图

一级缓存、二级缓存设计与查询流程分析图
- 一级缓存设计-类图

- 一级缓存工作流程图

- 二级缓存设计-类图

- 二级缓存工作流程图
