一、Executor功能概述
每一個sql語句的執行都會先到Executor執行器中在調用相應StatementHandler執行jdbc操作。源碼如下SimpleExecutor中的代碼片段
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException { Statement stmt = null; try { Configuration configuration = ms.getConfiguration();
//調用StatmentHandler,通過控制器調用jdbc相關操作 StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql); stmt = prepareStatement(handler, ms.getStatementLog()); return handler.query(stmt, resultHandler); } finally { closeStatement(stmt); } }
二、Executor繼承體系如下
Executor 執行器接口,它有兩個實現類,分別是BaseExecutor
和 CachingExecutor
。
BaseExecutor
:是一個抽象類,這種通過抽象的實現接口的方式是適配器設計模式之接口適配
的體現,是 Executor 的默認實現,實現了大部分 Executor 接口定義的功能,降低了接口實現的難度。BaseExecutor 的子類有三個,分別是SimpleExecutor
、ReuseExecutor
和BatchExecutor
。
SimpleExecutor: 簡單執行器,是 MyBatis 中默認使用的執行器,每執行一次 update 或 select,就開啟一個 Statement 對象,用完就直接關閉 Statement 對象(可以是 Statement 或者是 PreparedStatment 對象)
ReuseExecutor: 可重用執行器,這里的重用指的是重復使用 Statement,它會在內部使用一個 Map 把創建的 Statement 都緩存起來,每次執行 SQL 命令的時候,都會去判斷是否存在基於該 SQL 的 Statement 對象,如果存在 Statement 對象並且對應的 connection 還沒有關閉的情況下就繼續使用之前的 Statement 對象,並將其緩存起來。每個SqlSession 都有一個新的 Executor 對象,所以我們緩存在 ReuseExecutor 上的Statement 作用域是同一個 SqlSession。
BatchExecutor: 批處理執行器,用於將多個SQL一次性輸出到數據庫
CachingExecutor
: 緩存執行器,先從緩存中查詢結果,如果存在,就返回;如果不存在,再委托給 Executor delegate 去數據庫中取,delegate 可以是上面任何一個執行器,默認是simpleexecutor
三、Executor創建過程源碼分析
(1)創建SqlSession時,可以指定Executor類型,mybatis中ExecutorType枚舉類來指定,ExecutorType源碼如下,分別指定BaseExecutor下面三個實現類
public enum ExecutorType { SIMPLE, REUSE, BATCH }
(2)根據傳遞ExecutorType類型可以指定Executor種類,默認不傳參就是SimpleExecutor
SqlSession sqlsession=sqlsessionFactory.openSession();
//SqlSession sqlsession=sqlsessionFactory.openSession(ExecutorType.REUSE);
(3)、DefaultSqlSessionFactory中創建執行器,源碼如下
public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { //定義事物 Transaction tx = null; try { //mybatis配置文件中所有信息都封裝到Configuration中,獲取環境 ,Environment中有id、datasource、transactionFactory三個屬性 final Environment environment = configuration.getEnvironment(); //獲取事物工廠 final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment); //根據工廠創建事物對象,直接 return new JdbcTransaction(ds, level, autoCommit); tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit); //創建執行器 final Executor executor = configuration.newExecutor(tx, execType); //默認executor是CachingExecutor return new DefaultSqlSession(configuration, executor, autoCommit); } catch (Exception e) { closeTransaction(tx); // may have fetched a connection so lets call close() throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } }
(4)下面看執行器具體創建流程configuration.newExecutor(tx, execType)
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
//默認創建簡單執行器 executorType = executorType == null ? defaultExecutorType : executorType; executorType = executorType == null ? ExecutorType.SIMPLE : executorType; Executor executor; if (ExecutorType.BATCH == executorType) { executor = new BatchExecutor(this, transaction); } else if (ExecutorType.REUSE == executorType) { executor = new ReuseExecutor(this, transaction); } else { executor = new SimpleExecutor(this, transaction); }
//cacheEnabled默認ture開啟二級緩存 if (cacheEnabled) {
//把簡單執行器傳遞給CachingExecutor中的delegate屬性, executor = new CachingExecutor(executor); }
//mybatis責任鏈模式 executor = (Executor) interceptorChain.pluginAll(executor); return executor; }
public CachingExecutor(Executor delegate) {
this.delegate = delegate;
delegate.setExecutorWrapper(this);
}
(5)執行流程入下