MyBatis源碼(五)之動態Sql解析運行階段參數處理

上篇博文分析到Mapper文件的讀取,以及啓動過程動態Sql的解析部分 MyBatis源碼(四)之mapper文件解析和動態Sql解析啓動階段

本博文繼續動態Sql的解析,在運行時的解析。前文也提過,在動態Sql中,sql的最終生成是依靠傳入的參數來決定的。所以在繼續分析之前先來分析下是mybatis是怎麼接收參數的。

dao參數上可能有@Param註解,參數中可能有集合Collection,如何跟之前配置文件中的javaType,parameterType對應起來等等。

dao的代理類MapperProxy的invoke方法,invoke能獲取到攔截的方法的元數據信息和入參
去掉Object的方法之後攔截所有的dao方法。

跟進看下攔截Dao的方法是具體做什麼的

MapperMethod

MapperMethod的一個成員MethodSignature,也是MapperMethod的內部類(mybatis的一個特點是比較喜歡使用內部類)重點看下參數部分:

MethodSignature

MapperMethod封裝了被攔截方法的信息,包括:

返回類型
是否返回多行
是否有ResultHandler接口類型的參數
被攔截方法的參數信息

如下dao方法對應上面的截圖:

List<HrdDemandMatching> batchQueryBySellerIds(@Param("demandId")Long demandId,
                @Param("sellerMemberIdLs") List<String> sellerMemberIdLs);

如果方法在有一個參數 就是 params就在添加一個key和value對 2= 2
key表示參數的下標2
value表示參數的名字(被註解@param標示) 沒有的話value也是下標 即這裏的 2 = 2
MethodSignature的這個params的TreeMap只是參數下標和名字而已,此時並沒有放入參數,下面將參數填入參數值。
MapperMethod執行
MethodSignature將參數填入參數值

代理攔截方法之後委託給mapperMethod.execute還行,
covertArgsToSqlCommandParam這個方法將參數值和參數名對應起來,返回的是Object。

1)沒有參數返回null
2)1個參數返回args[0]
3)多於1個返回Map,key:有@param註解的名字,沒有param取下標

第三條除了將參數名和值放入map 同時又額外添加了一份參數的信息
如這裏的param1和param2第一個下標參數的值,第二個下標參數的值,本博文後邊還會用到這個!

其實MapperMethod.execute方法主要的是組織入參,選擇執行SqlSession的那個方法 根據標籤 select insert update delete和方法的返回值類型。

現在還沒有完,還要方法參數轉換成配置文件中對應的值和類型才完工。參數映射部分纔剛剛開始!!
我們繼續跟代碼,這一步就是根據具體的 select insert等標籤或者返回值決定調用那個具體的sqlsessionTemplate的方法(也是SqlSession的方法)
這裏寫圖片描述
這裏寫圖片描述
還記得嗎 這裏的SqlSession值的是誰?SqlSessionTemplate
SqlSessionTemplate的成員sqlSessionProxy – SqlSessionInterceptor,
SqlSessionTemplate也實現了SqlSession,所有的SqlSession方法都是用這個sqlSessionProxy 完成的,所有sqlSessionTemplate的方法都會被SqlSessionInterceptor攔截住,進而獲取真正的SqlSession的實現,通過DefaultSqlSessionFactory.openSession創建DefaultSqlSession(SimpletExecutor,Transaction也都創建並且塞入到DefaultSqSession了)!!!這是如果忘記了可以看下之前的博文。
SqlSessionTemplate的成員SqlsessionInterceptor創建DefaultSqlSession
這裏不再複述,只是貼下代碼如讀者回憶一下。

接下來進入到DefaultSqlSession的方法

DefaultSqlSession.selectList

DefaultSqlSession.selectList()方法SimpleExecutor.query方法的參數
wrapCollection(parameter)這個方法也值得看下:
dao方法超過兩個會被當成map,兩個以內是原生的對象類型,
該方法處理集合類型具體規則如下:

1、集合類型非map類型的直接map.put(“collection”,object);
2、集合類型是List的map.put("list",object)
3、數組map.put("array",object)

可見,只要超過兩個參數的都會轉成map collection和array的也不例外,都是map。

這裏寫圖片描述

本篇將的主要是dao的參數是如何傳入和處理的,貼圖較多是爲了讓大家回顧下之前的流程不要看過忘了:

兩個以內的參數都是不做轉換,如果是collection的或者array會轉換成map
兩個參數或者以上,直接轉成map。

這裏請求流程只是到了SimpleExecutor.execute
將dao的參數處理完畢了,但是參數是怎麼跟sql中的入參對接上,以及sql是如何根據參數生成最終執行的sql還沒有討論。

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