一、MyBatis的Executor执行器详解
1. MyBatis执行器类型
MyBatis有三种核心执行器实现,在org.apache.ibatis.executor
包中定义:
执行器类型 | 特点描述 |
---|---|
SimpleExecutor | 默认执行器,每次执行都会创建新的Statement对象 |
ReuseExecutor | 重用预处理语句(PreparedStatement),减少重复编译 |
BatchExecutor | 批量操作执行器,将多个更新操作合并批处理 |
CachingExecutor | 装饰器模式实现,为其他执行器提供二级缓存功能 |
2. 各执行器实现原理与区别
2.1 SimpleExecutor
-
工作原理:
-
每次执行update或query都会创建新的PreparedStatement
-
执行完毕后立即关闭Statement
-
-
优点:实现简单,无状态,线程安全
-
缺点:频繁创建/关闭Statement,性能开销较大
-
适用场景:常规单条SQL操作
2.2 ReuseExecutor
-
工作原理:
-
维护一个Statement缓存Map(key为SQL语句)
-
相同SQL重复使用已创建的PreparedStatement
-
-
优点:减少SQL预编译开销,提升重复SQL执行效率
-
缺点:需要维护Statement缓存,长时间不用的Statement不会主动关闭
-
适用场景:短时间内重复执行相同SQL语句
2.3 BatchExecutor
-
工作原理:
-
将多个update操作缓存起来
-
等待显式调用flushStatements()时批量提交
-
使用JDBC的addBatch()/executeBatch()机制
-
-
优点:大幅提升批量操作性能(减少网络往返)
-
缺点:需要手动控制批量提交时机
-
适用场景:批量插入、更新、删除操作
2.4 CachingExecutor
-
特殊性质:
-
装饰器模式实现,不单独使用
-
为其他执行器添加二级缓存功能
-
通过TransactionalCacheManager管理缓存事务
-
-
工作流程:
-
先查询二级缓存
-
缓存未命中时委托给被装饰的执行器执行
-
将结果存入缓存
-
3. 执行器配置与选择
配置方式(mybatis-config.xml):
xml
<settings>
<!-- 可选值:SIMPLE(默认), REUSE, BATCH -->
<setting name="defaultExecutorType" value="REUSE"/>
</settings>
代码中临时切换:
java
SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH);
try {
UserMapper mapper = session.getMapper(UserMapper.class);
// 批量操作...
session.commit();
} finally {
session.close();
}
4. 执行器选择建议
-
常规CRUD:使用默认的SimpleExecutor即可
-
高频重复SQL:考虑使用ReuseExecutor
-
批量数据处理:显式使用BatchExecutor
-
缓存需求:配合CachingExecutor使用
二、MyBatis半自动ORM特性解析
1. ORM工具分类标准
特性 | 全自动ORM | 半自动ORM |
---|---|---|
SQL生成 | 框架自动生成 | 开发者编写 |
对象-关系映射 | 自动映射 | 显式配置 |
学习曲线 | 较陡峭 | 较平缓 |
灵活性 | 较低 | 较高 |
性能控制 | 较难优化 | 易于优化 |
典型代表 | Hibernate, JPA | MyBatis |
2. MyBatis作为半自动ORM的核心表现
-
SQL控制权:
-
开发者需要手动编写和维护SQL语句
-
可以精确控制每个查询的细节
-
支持原生SQL和动态SQL
-
-
映射配置:
-
需要显式定义ResultMap/ResultType
-
关联关系需要手动配置(嵌套查询/嵌套结果)
-
支持高级映射(构造函数映射、鉴别器等)
-
-
会话管理:
-
需要手动管理SqlSession生命周期
-
显式控制事务边界
-
-
延迟加载:
-
需要手动配置fetchType="lazy"
-
理解SqlSession作用域对延迟加载的影响
-
3. 半自动与全自动ORM的典型区别
查询示例对比:
JPA (全自动)
java
// 自动生成SQL:SELECT * FROM users WHERE name = ?
List<User> users = entityManager.createQuery(
"SELECT u FROM User u WHERE u.name = :name", User.class)
.setParameter("name", "张三")
.getResultList();
MyBatis (半自动)
xml
<!-- 需手动编写SQL -->
<select id="findByName" resultType="User">
SELECT * FROM users WHERE name = #{name}
</select>
java
// 执行明确映射的SQL
List<User> users = sqlSession.selectList("findByName", "张三");
4. 半自动设计的优势与代价
优势:
-
性能可控:可优化每一句SQL
-
灵活性强:支持复杂查询和存储过程
-
过渡平滑:适合从原生JDBC迁移
-
技术债务少:避免全自动ORM的"魔法"行为
代价:
-
开发效率:需要编写更多样板代码
-
维护成本:SQL分散在XML/注解中
-
移植性:数据库方言差异需要手动处理
三、MyBatis核心理解与架构剖析
1. MyBatis架构全景图
text
[应用程序]
|
v
[MyBatis API] (SqlSession, MapperProxy)
|
v
[核心执行流程]
|-- 配置解析
|-- SQL解析
|-- 参数处理
|-- SQL执行
|-- 结果映射
|
v
[JDBC]
2. 核心组件与工作流程
-
配置阶段:
-
解析mybatis-config.xml全局配置
-
加载Mapper.xml映射文件
-
构建Configuration对象(包含所有配置信息)
-
-
会话阶段:
-
创建SqlSessionFactory
-
开启SqlSession(包含Executor实例)
-
获取Mapper接口代理对象(MapperProxy)
-
-
执行阶段:
-
参数处理(TypeHandler)
-
SQL解析(包括动态SQL)
-
执行查询/更新(通过Executor)
-
结果映射(ResultSetHandler)
-
-
缓存体系:
-
一级缓存(SqlSession级别)
-
二级缓存(Mapper级别)
-
3. MyBatis的核心价值主张
-
SQL与代码分离:
-
SQL保存在XML/注解中
-
业务代码不掺杂SQL字符串拼接
-
-
简化JDBC但不隐藏:
-
封装了样板代码(连接管理、结果集遍历等)
-
仍保持对JDBC底层访问的能力
-
-
灵活的结果映射:
-
支持简单POJO到复杂嵌套对象
-
可自定义TypeHandler处理特殊类型
-
-
插件扩展体系:
-
可拦截四大核心组件
-
实现分页、审计等通用功能
-
4. 适用场景分析
最适合场景:
-
需要高度优化SQL性能的项目
-
遗留数据库或复杂数据库模式
-
需要调用存储过程的系统
-
对SQL有深度控制需求的团队
不太适合场景:
-
快速原型开发
-
简单CRUD为主的应用程序
-
需要跨数据库移植的项目
5. MyBatis的演进趋势
-
注解支持增强:
-
@Select, @Insert等注解功能不断完善
-
动态SQL也可以通过@SelectProvider实现
-
-
Spring Boot整合:
-
MyBatis-Spring-Boot-Starter简化配置
-
自动发现Mapper接口
-
-
Kotlin支持:
-
更好的Kotlin DSL支持
-
协程等现代特性整合
-
-
响应式编程:
-
实验性的响应式MyBatis实现
-
集成R2DBC等响应式驱动
-
四、总结对比表格
执行器对比
执行器类型 | 线程安全 | Statement重用 | 批量支持 | 缓存支持 | 适用场景 |
---|---|---|---|---|---|
SimpleExecutor | 是 | 否 | 否 | 需装饰 | 常规操作 |
ReuseExecutor | 是 | 是(SQL级别) | 否 | 需装饰 | 重复SQL高频执行 |
BatchExecutor | 是 | 是 | 是 | 需装饰 | 批量插入/更新 |
CachingExecutor | 是 | 依赖被装饰者 | 依赖被装饰者 | 是 | 需要二级缓存的场景 |
ORM类型对比
特性维度 | 全自动ORM | MyBatis(半自动) |
---|---|---|
学习成本 | 较高 | 中等 |
开发效率 | 高(简单CRUD) | 中(需写SQL) |
性能优化 | 较难 | 容易 |
复杂查询支持 | 有限 | 强大 |
数据库移植性 | 好 | 需手动调整 |
社区生态 | 丰富(JPA) | 非常丰富 |