MyBatis 四大組件 Executor 執行器


一、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 的子類有三個,分別是SimpleExecutorReuseExecutorBatchExecutor

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)執行流程入下

 

   


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM