sql執行器,其對應的類全路徑:org.apache.ibatis.executor.Executor。java
Executor 執行器根據接口,定義update(更新或插入)、query(查詢)、commit(提交事務)、rollback(回滾事務)。接下來簡單介紹幾個重要方法:sql
CachingExecutor 支持結果緩存的SQL執行器,注意其設計模式的應用,該類中,會持有Executor的一個委託對象,CachingExecutor關注與緩存特定的邏輯,其最終的SQL執行由其委託對象來實現,即其內部的委託對象爲BaseExecutor的實現類。apache
BaseExecutor Executor的基礎實現類,該類爲抽象類,關於查詢、更新具體的實現由其子類來實現,下面4個都是其子類。設計模式
SimpleExecutor 簡單的Executor執行器。緩存
BatchExecutor 支持批量執行的Executor執行器。併發
ClosedExecutor 表示一個已關閉的Executor。app
ReuseExecutor 支持重複使用Statement,以SQL爲鍵,緩存Statement對象。源碼分析
在Mybatis中,Executor的建立由Configuration對象來建立,具體的代碼以下:學習
public Executor newExecutor(Transaction transaction) {
return newExecutor(transaction, defaultExecutorType); // @1
}
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
executorType = executorType == null ? defaultExecutorType : executorType;
executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
Executor executor;
if (ExecutorType.BATCH == executorType) { // @2
executor = new BatchExecutor(this, transaction);
} else if (ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction);
} else {
executor = new SimpleExecutor(this, transaction);
}
if (cacheEnabled) { // @3
executor = new CachingExecutor(executor);
}
executor = (Executor) interceptorChain.pluginAll(executor); // @4
return executor;
}
複製代碼
從上面的代碼能夠看出,Executor的建立由以下三個關鍵點: 代碼@1:默認的ExecutorType爲ExecutorType.SIMPLE,即默認建立的Executory爲SimpleExecutor。 代碼@2:根據executorType的值建立對應的Executory。 代碼@3:若是cacheEnabled爲true,則建立CachingExecutory,而後在其內部持有上面建立的Executor,cacheEnabled默認爲true,則默認建立的Executor爲CachingExecutor,而且其內部包裹着SimpleExecutor。 代碼@4:使用InterceptorChain.pluginAll爲executor建立代理對象,即Mybatis的拆件機制,將在該系列文章中詳細介紹。this
在學習StatementHandler以前,咱們先來回顧一下JDBC相關的知識。JDBC與語句執行的兩大主流對象:java.sql.Statement、java.sql.PrepareStatement對象你們應該不會陌生,該對象的execute方法就是執行SQL語句的入口,經過java.sql.Connection對象建立Statement對象。Mybatis的StatementHandler,是Mybatis建立Statement對象的處理器,即StatementHandler會接管Statement對象的建立。
StatementHandler 根接口,咱們重點關注一下其定義的方法:
BaseStatementHandler StatementHandler的抽象實現類,SimpleStatementHandler、PrepareStatementHandler、CallableStatementHandler是其子類。 咱們來一一看一下其示例變量:
SimpleStatementHandler 具體的StatementHandler實現器,java.sql.Statement對象建立處理器。
PrepareStatementHandler java.sql.PrepareStatement對象的建立處理器。
CallableStatementHandler java.sql.CallableStatement對象的建立處理器,可用來執行存儲過程調用的Statement。
RoutingStatementHandler StatementHandler路由器,咱們看一下其構造方法後,就會對該類瞭然於胸。
public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
switch (ms.getStatementType()) { // @1
case STATEMENT:
delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
case PREPARED:
delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
case CALLABLE:
delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
default:
throw new ExecutorException("Unknown statement type: " + ms.getStatementType());
}
}
複製代碼
原來是會根據MappedStatement對象的statementType建立對應的StatementHandler。
public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql); // @1
statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler); // @2
return statementHandler;
}
複製代碼
該方法的兩個關鍵點以下: 代碼@1:建立RoutingStatementHandler對象,在其內部再根據SQL語句的類型,建立對應的StatementHandler對象。 代碼@2:對StatementHandler引入拆件機制,該部分將在該專題的後續文章中會詳細介紹,這裏暫時跳過。
參數處理器。一樣咱們先來看一下其類圖。
public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement, parameterObject, boundSql);
parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler); // @1
return parameterHandler;
}
複製代碼
一樣該接口也支持插件化機制。
處理結果的Handler。咱們一樣看一下其類圖。
public ResultSetHandler newResultSetHandler(Executor executor, MappedStatement mappedStatement, RowBounds rowBounds, ParameterHandler parameterHandler, ResultHandler resultHandler, BoundSql boundSql) {
ResultSetHandler resultSetHandler = new DefaultResultSetHandler(executor, mappedStatement, parameterHandler, resultHandler, boundSql, rowBounds);
resultSetHandler = (ResultSetHandler) interceptorChain.pluginAll(resultSetHandler);
return resultSetHandler;
}
複製代碼
一樣支持插件化機制,咱們也稍微再看一下其調用鏈:
能夠看出其調用的入口爲SQL執行時。本文做爲下一篇《源碼分析Mybatis整合ShardingJdbc SQL執行流程》的前置篇,重點介紹Executor、StatementHandler、ParameterHandler、ResultSetHandler的具體職責,以類圖爲基礎並詳細介紹其核心方法的做用,而後詳細介紹了這些對象是如何建立,並引出Mybatis拆件機制。
做者介紹:《RocketMQ技術內幕》做者,維護公衆號:中間件興趣圈,目前主要發表了源碼閱讀java集合、JUC(java併發包)、Netty、ElasticJob、Mycat、Dubbo、RocketMQ、mybaits等系列源碼。