1阅嘶、mybatis執(zhí)行入口
前一篇已經(jīng)分析過SqlSession內(nèi)的getMapper方法萝衩,最終是通過configuration生成了MapperProxy代理類。所有mapper的如果其實(shí)是通過MapperProxy代理執(zhí)行俱两,代碼如下
args參數(shù)為mapper方法執(zhí)行調(diào)用的參數(shù)
image.png
實(shí)際執(zhí)行者為MapperMethod類的execute赎线,此文主要分析select執(zhí)行過程
image.png
上圖紅框的內(nèi)容第一處為參數(shù)的初步解析,我們看下源碼處理钥弯,實(shí)際是通過ParamNameResolver進(jìn)行初步的映射關(guān)系存儲(chǔ)径荔,names存儲(chǔ)參數(shù)名的順利映射,參數(shù)名若有注解Param則為注解內(nèi)的參數(shù)名脆霎,否者參數(shù)名為方法內(nèi)的參數(shù)名总处。
getNamedParams方法則將mapper調(diào)用的參數(shù)和names內(nèi)的參數(shù)映射,方法如下
image.png
image.png
image.png
初步參數(shù)解析成為一個(gè)map將存儲(chǔ)參數(shù)名和實(shí)際值的映射
二睛蛛、參數(shù)解析執(zhí)行過程
實(shí)際核心執(zhí)行者為Executor
我們看看BaseExecutor對(duì)于query的實(shí)現(xiàn)鹦马,隱約可以看到緩存的痕跡此處不分析,圖中可以看出BoundSql是由MappedStatement獲取的下面分析生成過程
image.png
BoundSql為sql的詳細(xì)信息忆肾,參數(shù)解析則存在未生成BoundSql的方法內(nèi)荸频,先看看BoundSql的信息下圖可以看出,內(nèi)部有sql信息及詳細(xì)映射信息
image.png
核心生成過程是有sqlSource實(shí)現(xiàn)
image.png
sqlSource相關(guān)的子類信息客冈,主要分析DynamicSqlSource
image.png
主要解析由SqlSourceBuilder實(shí)現(xiàn)
image.png
SqlSourceBuilder源碼
image.png
由GenericTokenParser類處理#{}內(nèi)部的參數(shù)旭从,將sql語句內(nèi)的#{}替換成問號(hào),并且生成
相應(yīng)的ParameterMapping對(duì)象,ParameterMapping內(nèi)容如下
image.png
expression為#{}內(nèi)的內(nèi)容和悦,closeToken為‘}’退疫,openToken為‘#{’
image.png
ParameterMappingTokenHandler處理,將#{}替換成鸽素?蹄咖,然后解析語句內(nèi)容生成ParameterMapping對(duì)象放入parameterMappings中
到此BoundSql的解析過程基本結(jié)束。
回到BaseExecutor查看執(zhí)行過程付鹿,先判斷有沒有緩存有緩存直接返回內(nèi)容澜汤,沒有緩存則執(zhí)行數(shù)據(jù)庫查詢操作
最終的執(zhí)行者為StatementHandler
image.png
看看SimpleStatementHandler的具體實(shí)現(xiàn),由Statement實(shí)行boundSql內(nèi)的sql舵匾,下圖可以看出結(jié)果的映射是由ResultSetHandler處理
image.png
Statement的參數(shù)化則在BaseExecutor內(nèi)
image.png
參數(shù)化的詳細(xì)過程主要在DefaultParameterHandler內(nèi)的setParameters下面看源碼俊抵,主要是根據(jù)前期解析出來的ParameterMapping集合,從boundSql內(nèi)取參數(shù)賦值坐梯,沒有的話根據(jù)parameterObject是否有處理類判斷賦值
image.png
三徽诲、結(jié)果映射執(zhí)行過程
ResultSetHandler接口處理
image.png
結(jié)果的主要由DefaultResultSetHandler類處理,該類的mappedStatement及其先關(guān)信息都是由Configuration生成
image.png
handleResultSet方法中resultHandler為null是使用DefaultResultHandler處理
image.png
主要看看handleRowValuesForSimpleResultMap的執(zhí)行過程
image.png
rowValue為處理后映射的結(jié)果對(duì)象吵血,我們看看getRowValue如何處理
skipRows跳過邏輯分頁如果RowBounds設(shè)置了offset則會(huì)將offset前的結(jié)果集忽略掉谎替,曾經(jīng)遇到過一次分頁插件bug就是由于分頁對(duì)象繼承RowBounds設(shè)置了offset導(dǎo)致分頁結(jié)果錯(cuò)誤
image.png
getRowValue
主要由createResultObject來創(chuàng)建結(jié)果對(duì)象
由applyAutomaticMappings和applyPropertyMappings來完成對(duì)象和結(jié)果集的映射
image.png
createResultObject中由ResultMap的getType方法取得結(jié)果類型生成相應(yīng)的對(duì)象
image.png
再由applyPropertyMappings方法完成對(duì)象的映射
image.png