天天看點

Mybatis Insert、update、delete流程

上文mybatis源碼簡書我們講到sqlsession中通過executor來執行sql,我們接着往下看

Mybatis Insert、update、delete流程
update方法點進去,我們進到baseexecutor
Mybatis Insert、update、delete流程

這裡我們看到 clearLocalCache 方法,可見每次更新都會清除緩存

我們再看到doUpdate

1 public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
 2     Statement stmt = null;
 3     try {
 4       Configuration configuration = ms.getConfiguration();
 5       StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
 6       stmt = prepareStatement(handler, ms.getStatementLog());
 7       return handler.update(stmt);
 8     } finally {
 9       closeStatement(stmt);
10     }
11   }      

先看第5行,生成一個 StatementHandler,StatementHandler是mybatis4大對象之一,負責處理Mybatis與JDBC之間Statement的互動。

我們再看下newStatementHandler,

Mybatis Insert、update、delete流程

這裡又看 RoutingStatementHandler,先不管,再點進去,會發現會有不同類型的StatementHandler

Mybatis Insert、update、delete流程
SimpleStatementHandler,這個很簡單了,就是對應我們JDBC中常用的Statement接口,用于簡單SQL的處理;
PreparedStatementHandler,這個對應JDBC中的PreparedStatement,預編譯SQL的接口;
CallableStatementHandler,這個對應JDBC中CallableStatement,用于執行存儲過程相關的接口;
RoutingStatementHandler,這個接口是以上三個接口的路由,沒有實際操作,隻是負責上面三個StatementHandler的建立及調用。      

這幾個StatementHandler他有共同的構造器,都在BaseStatementHandler

1 protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
 2     this.configuration = mappedStatement.getConfiguration();
 3     this.executor = executor;
 4     this.mappedStatement = mappedStatement;
 5     this.rowBounds = rowBounds;
 6 
 7     this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
 8     this.objectFactory = configuration.getObjectFactory();
 9 
10     if (boundSql == null) { // issue #435, get the key before calculating the statement
11       generateKeys(parameterObject);
12       boundSql = mappedStatement.getBoundSql(parameterObject);
13     }
14 
15     this.boundSql = boundSql;
16 
17     this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
18     this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);
19   }      

這裡順便建立了parameterHandler和 resultSetHandler

parameterHandler的作用就是進行參數預編譯設定,resultSetHandler封裝我們得到的結果。

public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
 2     Statement stmt = null;
 3     try {
 4       Configuration configuration = ms.getConfiguration();
 5       StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
 6       stmt = prepareStatement(handler, ms.getStatementLog());
 7       return handler.update(stmt);
 8     } finally {
 9       closeStatement(stmt);
10     }
11   }      

再看第六行,我們在生成StatementHandler,開始執行prepareStatement

1 private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
2     Statement stmt;
3     Connection connection = getConnection(statementLog);
4     //調用StatementHandler.prepare
5     stmt = handler.prepare(connection);
6     //調用StatementHandler.parameterize
7     handler.parameterize(stmt);
8     return stmt;
9   }      

我們看到prepare方法,生成statement,用過jdbc的都知道,Statement對象主要用于将 SQL 語句發送到資料庫中,執行對資料庫的資料的檢索或者更新

Mybatis Insert、update、delete流程
Mybatis Insert、update、delete流程

生成好statement後,我們再看下第7行

public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
 2     Statement stmt = null;
 3     try {
 4       Configuration configuration = ms.getConfiguration();
 5       StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
 6       stmt = prepareStatement(handler, ms.getStatementLog());
 7       return handler.update(stmt);
 8     } finally {
 9       closeStatement(stmt);
10     }
11   }      

 這裡就是真正的執行sql的地方。

Mybatis Insert、update、delete流程