1、mybatis執行入口
前一篇已經分析過SqlSession內的getMapper方法,最終是通過configuration生成了MapperProxy代理類。所有mapper的如果其實是通過MapperProxy代理執行,代碼如下
args參數為mapper方法執行調用的參數
image.png
實際執行者為MapperMethod類的execute,此文主要分析select執行過程
image.png
上圖紅框的內容第一處為參數的初步解析,我們看下源碼處理,實際是通過ParamNameResolver進行初步的映射關系存儲,names存儲參數名的順利映射,參數名若有注解Param則為注解內的參數名,否者參數名為方法內的參數名。
getNamedParams方法則將mapper調用的參數和names內的參數映射,方法如下
image.png
image.png
image.png
初步參數解析成為一個map將存儲參數名和實際值的映射
二、參數解析執行過程
實際核心執行者為Executor
我們看看BaseExecutor對于query的實現,隱約可以看到緩存的痕跡此處不分析,圖中可以看出BoundSql是由MappedStatement獲取的下面分析生成過程
image.png
BoundSql為sql的詳細信息,參數解析則存在未生成BoundSql的方法內,先看看BoundSql的信息下圖可以看出,內部有sql信息及詳細映射信息
image.png
核心生成過程是有sqlSource實現
image.png
sqlSource相關的子類信息,主要分析DynamicSqlSource
image.png
主要解析由SqlSourceBuilder實現
image.png
SqlSourceBuilder源碼
image.png
由GenericTokenParser類處理#{}內部的參數,將sql語句內的#{}替換成問號,并且生成
相應的ParameterMapping對象,ParameterMapping內容如下
image.png
expression為#{}內的內容,closeToken為‘}’,openToken為‘#{’
image.png
ParameterMappingTokenHandler處理,將#{}替換成?,然后解析語句內容生成ParameterMapping對象放入parameterMappings中
到此BoundSql的解析過程基本結束。
回到BaseExecutor查看執行過程,先判斷有沒有緩存有緩存直接返回內容,沒有緩存則執行數據庫查詢操作
最終的執行者為StatementHandler
image.png
看看SimpleStatementHandler的具體實現,由Statement實行boundSql內的sql,下圖可以看出結果的映射是由ResultSetHandler處理
image.png
Statement的參數化則在BaseExecutor內
image.png
參數化的詳細過程主要在DefaultParameterHandler內的setParameters下面看源碼,主要是根據前期解析出來的ParameterMapping集合,從boundSql內取參數賦值,沒有的話根據parameterObject是否有處理類判斷賦值
image.png
三、結果映射執行過程
ResultSetHandler接口處理
image.png
結果的主要由DefaultResultSetHandler類處理,該類的mappedStatement及其先關信息都是由Configuration生成
image.png
handleResultSet方法中resultHandler為null是使用DefaultResultHandler處理
image.png
主要看看handleRowValuesForSimpleResultMap的執行過程
image.png
rowValue為處理后映射的結果對象,我們看看getRowValue如何處理
skipRows跳過邏輯分頁如果RowBounds設置了offset則會將offset前的結果集忽略掉,曾經遇到過一次分頁插件bug就是由于分頁對象繼承RowBounds設置了offset導致分頁結果錯誤
image.png
getRowValue
主要由createResultObject來創建結果對象
由applyAutomaticMappings和applyPropertyMappings來完成對象和結果集的映射
image.png
createResultObject中由ResultMap的getType方法取得結果類型生成相應的對象
image.png
再由applyPropertyMappings方法完成對象的映射
image.png