MyBatis源碼-解讀Executor的三個實現類之ReuseExecutor(重用執行器)

在這裏插入圖片描述

Pre

MyBatis源碼-深入理解MyBatis Executor的設計思想

工程部分見
MyBatis源碼- SqlSession門面模式 & selectList 源碼解析

在這裏插入圖片描述

實際中,我們都是面向SqlSession編程的,不會直接調用Executor來執行業務邏輯,這裏我們僅僅是爲了深入瞭解下Executor體系架構才這麼搞的,切記。


Executor 執行器

在這裏插入圖片描述


接口繼承關係

在這裏插入圖片描述

這裏我們重點看下Executor的 三個實現子類。

分別是:SimpleExecutor(簡單執行器)、ReuseExecutor(重用執行器)、BatchExecutor(批處理執行器)。


ReuseExecutor(重用執行器)

迴歸下JDBC中的 Statement , 再和MyBatis 所封裝的 對比一下

在這裏插入圖片描述

PreparedStatement 支持預編譯參數

在這裏插入圖片描述

MyBatis的ReuseExecutor就是利用了JDBC Statement的這個特點 來處理的。

入門小demo


    @Test
    public void testReuseExecutor() throws SQLException {
        // 通過factory.openSession().getConnection()實例化JdbcTransaction ,用於構建ReuseExecutor
        jdbcTransaction = new JdbcTransaction(factory.openSession().getConnection());
        // 映射SQL
        ms = configuration.getMappedStatement("com.artisan.UserMapper.selectByid");

        // 實例化ReuseExecutor
        ReuseExecutor executor = new ReuseExecutor(configuration, jdbcTransaction);
        // 調用doQuery執行查詢
        List<User> userList = executor.doQuery(ms, 1, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER, ms.getBoundSql(1));
        System.out.println(userList.get(0));


        List<User> userList2 = executor.doQuery(ms, 1, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER, ms.getBoundSql(1));
        System.out.println(userList2.get(0));

    }

執行結果

在這裏插入圖片描述
可以看到 相同的SQL語句 會緩存對應的PrepareStatement , 緩存的生命週期: 會話有效期


源碼實現

在這裏插入圖片描述

Key 是 sql , Value 是 Statement

執行過程:

executor.doQuery ----> prepareStatement(handler, ms.getStatementLog())

---------> 見下方源碼

  private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
    Statement stmt;
    BoundSql boundSql = handler.getBoundSql();
    String sql = boundSql.getSql();
    if (hasStatementFor(sql)) {
      stmt = getStatement(sql);
      applyTransactionTimeout(stmt);
    } else {
      Connection connection = getConnection(statementLog);
      stmt = handler.prepare(connection, transaction.getTimeout());
      putStatement(sql, stmt);
    }
    handler.parameterize(stmt);
    return stmt;
  }

先判斷本地緩存statementMap是否有數據,有的話從statementMap獲取,沒有的話建立Statement,並存入本地緩存statementMap 。

注意這個緩存的聲明週期 是僅限於本次會話。 會話結束後,這些緩存都會被銷燬掉。

區別於SimpleExecutor的實現,多了個本地緩存。 推薦使用ReuseExecutor 。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章