天天看點

SpringBoot整合Mybatis-Plus源碼分析(九) SqlSession Insert流程

作者:愛好程式設計的程式員老徐

上文已經說到Dao代理對象經過一步步執行最後會調用到SqlSession對象,該對象是一個接口,具體實作類是DefaultSqlSession,調用該類的insert方法會調用update方法,該方法的截圖如下:

SpringBoot整合Mybatis-Plus源碼分析(九) SqlSession Insert流程

DefaultSqlSession的update方法

從截圖可以看成該方法從Configuration中擷取MappedStatement對象,接着調用BaseExecutor的update方法,update方法調用doUpdate()方法,方法截圖如下:

SpringBoot整合Mybatis-Plus源碼分析(九) SqlSession Insert流程

BaseExecutor的update方法截圖

該方法邏輯是從MappedStatement中擷取Configuration對象,通過調用Configuration的newStatementHandler方法,新建立一個RoutingStatementHandler對象,該對象實作了StatementHandler接口,該接口是Mybatis最為重要的一個接口,它的主要作用主要有:

1.SQL語句的生成:根據使用者傳遞的參數和配置的映射規則,StatementHandler接口會根據不同的操作(如查詢、插入、更新、删除)生成對應的SQL語句。

2.參數綁定:StatementHandler接口将根據生成的SQL語句和使用者傳遞的參數,将參數綁定到預編譯的SQL語句中,確定SQL語句中的占位符得到正确的值。

3.SQL語句的執行:StatementHandler接口将執行綁定好參數的SQL語句,與資料庫進行互動。它負責建立并管理JDBC的Statement對象,執行SQL語句并處理查詢結果。

4.結果集的處理:對于查詢操作,StatementHandler接口将擷取執行結果的資料集,并根據配置的映射規則将結果集映射為Java對象或集合。

通過上面羅列的幾條我們可以看出該對象的重要性,我們接着分析該對象有成員屬性StatementHandler的delegate變量,在構造方法時候判斷ms.getStatementType()的值是PREPARED,構造PreparedStatementHandler,該源碼截圖如下:

SpringBoot整合Mybatis-Plus源碼分析(九) SqlSession Insert流程

RoutingStatementHandler的構造方法截圖

由截圖看出delegate變量指派為PreparedStatementHandler,該對象主要實作了StatementHandler接口,通過調用父類的構造方法指派boundSql屬性,該屬性主要是要執行的sql語句的封裝,建立一個成員屬性為ParameterHandler對象,同時建立一個成員屬性為ResultSetHandler對象,該類的構造函數截圖如下:

SpringBoot整合Mybatis-Plus源碼分析(九) SqlSession Insert流程

PreparedStatementHandler的構造函數截圖

下面我們說一下ParameterHandler對象和ResultSetHandler對象的作用。

一、ParameterHandler對象的作用

1.參數設定:ParameterHandler接口負責将使用者傳遞的參數設定到預編譯的SQL語句中的占位符位置。它會根據SQL語句中的參數占位符的位置和參數的類型,将參數正确地綁定到SQL語句中。

2.參數轉換:ParameterHandler接口還負責将Java對象類型的參數轉換為資料庫所需的類型。這個過程通常涉及類型轉換、格式化和序列化等操作。

3.參數擷取:在某些情況下,我們可能需要在執行SQL語句之前擷取參數的值,例如在插入資料後擷取自動生成的主鍵。ParameterHandler接口提供了擷取參數值的方法,以便在需要時擷取參數的實際值。

二、ResultSetHandler對象的作用

1.結果集的映射:ResultSetHandler接口将根據配置的映射規則,将查詢結果集中的每一行資料映射為Java對象或集合。它會通過讀取結果集的中繼資料資訊和配置的映射規則,将每一行資料轉換為相應的Java對象。

2.結果集的處理:對于查詢操作,ResultSetHandler接口将處理查詢結果集中的每一行資料,并将其映射為Java對象或集合。它會根據映射規則設定Java對象的屬性值,并将對象添加到最終的結果集中。

3.結果集的分頁和排序:ResultSetHandler接口還可以進行結果集的分頁和排序操作,根據配置的分頁參數和排序規則,從整個結果集中提取出指定範圍的資料。

從上面分析ParameterHandler和ResultSetHandler作用可以看出,這兩個類與StatementHandler接口密切配合,共同完成SQL語句的執行任務。

在生成完StatementHandler對象以後,又調用了一個方法,該方法主要是調用了InterceptorChain的pluginAll方法,參數是StatementHandler對象,調用該方法擷取一個StatementHandler接口的代理類,該方法的主要作用是做分頁處理和一些定制化的執行,例如在sql語句執行之前設定一個時間,在執行之後設定一個時間,可以做到sql語句的執行時間功能,這個類是個插件,關于插件的分析大概在下下節會進行詳細的分析。

接着從目前線程擷取一個Connection對象,調用StatementHandler對象prepare方法傳入Connection對象,接着調用PreparedStatementHandler對象的prepare方法,又繼續調用instantiateStatement方法,該方法截圖如下:

SpringBoot整合Mybatis-Plus源碼分析(九) SqlSession Insert流程

PreparedStatementHandler的instantiateStatement方法

調用boundSql對象的getsql方法擷取要執行的sql語句,接着調用jdbc操作Connection對象的prepareStatement執行sql語句,傳回預編譯對象Statement,繼續調用StatementHandler對象的parameterize方法傳入Statement對象,該方法截圖如下:

SpringBoot整合Mybatis-Plus源碼分析(九) SqlSession Insert流程

StatementHandler對象的parameterize方法截圖

可以看出又調用了成員屬性ParameterHandler對象的setParameters對sql語句占位符就行填充值,該接口的實作類是MybatisParameterHandler,該方法截圖如下:

SpringBoot整合Mybatis-Plus源碼分析(九) SqlSession Insert流程

MybatisParameterHandler對象的setParameters方法

從BoundSql擷取List<ParameterMapping>集合,變量該集合擷取要替換的屬性列,反射擷取對象的屬性的值,擷取TypeHandler的類型,本例子中TypeHandler類型是StringTypeHandler,就是把屬性設定為string類型,設定完成以後又調用了StatementHandler對象的update方法最終調用JDBC PreparedStatement對象的execute執行最終傳回結果。

總結:

本篇文章分析了SqlSession的insert執行流程,該流程主要是建立了StatementHandler對象,繼而建立了ParameterHandler對象,由于本例子是新增操作沒有設定結果集的傳回,是以沒有說ResultSetHandler,這個我在下節分析查詢操作時候再詳細分析,最終還是調用JDBC的一些操作資料庫的方法,可見Mybati-Plus底層封裝了JDBC的操作,友善開發。我們下節見。