一、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) | 非常豐富 |