一、開篇:理解MyBatis的核心價值
在當今Java持久層框架生態中,MyBatis憑借其靈活的SQL控制能力和簡潔的ORM實現成為企業級應用的首選。與JPA的全自動ORM不同,MyBatis采用半自動化映射理念,在保持SQL靈活性的同時,通過智能映射減少70%的JDBC樣板代碼。
本文將深入剖析MyBatis的架構核心,通過源碼解析揭示其內部工作機制。閱讀本文后,您將掌握:
- MyBatis核心對象的職責與協作關系
- SQL從映射到執行的完整生命周期
- 配置文件加載的關鍵流程
- 執行器體系的運作原理
二、核心對象體系解析
1. 基礎組件關系圖
2. 核心對象職責說明
(1) SqlSessionFactoryBuilder
- 功能:根據配置信息構建SqlSessionFactory
- 生命周期:方法局部(構建后即可銷毀)
- 源碼關鍵路徑:
public class SqlSessionFactoryBuilder {public SqlSessionFactory build(Reader reader) {return build(reader, null, null);}public SqlSessionFactory build(InputStream inputStream) {return build(inputStream, null, null);}.....}
(2) SqlSessionFactory
- 功能:創建SqlSession實例
- 實現類:
DefaultSqlSessionFactory
- 核心方法:
public class DefaultSqlSessionFactory implements SqlSessionFactory {private final Configuration configuration;public DefaultSqlSessionFactory(Configuration configuration) {this.configuration = configuration;}@Overridepublic SqlSession openSession() {return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);}
......}
(3) SqlSession
- 功能:執行CRUD操作、獲取Mapper接口
- 實現類:
DefaultSqlSession
- 關鍵源碼:
public class DefaultSqlSession implements SqlSession {private final Configuration configuration;private final Executor executor;private final boolean autoCommit;private boolean dirty;private List<Cursor<?>> cursorList;public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {this.configuration = configuration;this.executor = executor;this.dirty = false;this.autoCommit = autoCommit;}public DefaultSqlSession(Configuration configuration, Executor executor) {this(configuration, executor, false);}@Overridepublic <T> T selectOne(String statement) {return this.selectOne(statement, null);}......}
(4) Executor執行器
類型 | 特點 | 適用場景 |
---|---|---|
SimpleExecutor | 每次執行創建新Statement | 常規操作 |
ReuseExecutor | 復用預處理Statement | 高頻相同SQL操作 |
BatchExecutor | 批量操作優化 | 大批量數據插入/更新 |
(5) StatementHandler
- 職責鏈:
- 準備Statement對象
- 參數綁定
- 執行SQL
- 結果集映射
- 核心實現:
PreparedStatementHandler
三、配置文件加載機制深度解析
1. 配置文件加載流程
2. 核心源碼分析(MyBatis 3.5.10)
(1) XMLConfigBuilder 關鍵路徑
public Configuration parse() {parseConfiguration(parser.evalNode("/configuration"));return configuration;
}private void parseConfiguration(XNode root) {propertiesElement(root.evalNode("properties"));typeAliasesElement(root.evalNode("typeAliases"));pluginsElement(root.evalNode("plugins"));objectFactoryElement(root.evalNode("objectFactory"));objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));settingsElement(root.evalNode("settings"));environmentsElement(root.evalNode("environments"));databaseIdProviderElement(root.evalNode("databaseIdProvider"));typeHandlerElement(root.evalNode("typeHandlers"));mapperElement(root.evalNode("mappers"));
}
(2) Mapper解析核心邏輯
// XMLMapperBuilder.java
private void configurationElement(XNode context) {String namespace = context.getStringAttribute("namespace");// 解析緩存配置cacheRefElement(context.evalNode("cache-ref"));cacheElement(context.evalNode("cache"));// 解析SQL片段sqlElement(context.evalNodes("/mapper/sql"));// 解析CRUD操作buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
}
四、SQL執行全鏈路剖析
1. 執行流程時序圖
2. 核心階段源碼分析
(1) 執行器選擇策略
// DefaultSqlSessionFactory.java
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {final Executor executor = configuration.newExecutor(tx, execType);return new DefaultSqlSession(configuration, executor, autoCommit);
}
(2) 參數綁定過程
// DefaultParameterHandler.java
public void setParameters(PreparedStatement ps) {for (int i = 0; i < parameterMappings.size(); i++) {ParameterMapping parameterMapping = parameterMappings.get(i);Object value;String property = parameterMapping.getProperty();// 獲取參數值(支持復雜對象導航)value = parameterMapping.getTypeHandler().getParameter(parameterObject, property);// 設置到PreparedStatementtypeHandler.setParameter(ps, i + 1, value, jdbcType);}
}
(3) 結果集映射核心邏輯
// DefaultResultSetHandler.java
public List<Object> handleResultSets(Statement stmt) throws SQLException {final List<Object> multipleResults = new ArrayList<>();ResultSetWrapper rsw = getFirstResultSet(stmt);// 遍歷結果集while (rsw != null) {// 處理單結果集Object resultObject = handleResultSet(rsw, resultMaps);multipleResults.add(resultObject);rsw = getNextResultSet(stmt);}return collapseSingleResultList(multipleResults);
}
五、生產級最佳實踐
1. SqlSession使用規范
// 正確用法:確保資源釋放
try (SqlSession session = sqlSessionFactory.openSession()) {UserMapper mapper = session.getMapper(UserMapper.class);User user = mapper.findById(101);// 業務處理...
} // 自動關閉session
2. 執行器選擇策略
場景 | 推薦執行器 | 配置方式 |
---|---|---|
常規單條操作 | SimpleExecutor | 默認配置 |
批量更新操作 | BatchExecutor | openSession(ExecutorType.BATCH) |
高并發重復SQL | ReuseExecutor | openSession(ExecutorType.REUSE) |
3. 二級緩存陷阱規避方案
問題場景:
<!-- 錯誤配置:導致臟讀 -->
<cache/>
解決方案:
<!-- 正確配置:啟用事務緩存 -->
<cache type="org.apache.ibatis.cache.TransactionalCache"/>
六、總結
本文深入剖析了MyBatis的核心架構與運行機制,關鍵要點包括:
- 核心對象職責:
SqlSessionFactory
、Executor
、StatementHandler
的協作關系 - 配置文件加載:XML解析與
Configuration
對象構建過程 - SQL執行全鏈路:從映射到結果集轉換的完整流程