Mybatis返回集合類型到底是空集合還是null?源碼解讀

語言: CN / TW / HK

Mybatis 作為國內開發中常用到的半自動 orm 框架,相信大家都很熟悉,它提供了簡單靈活的xml映射配置,方便開發人員編寫簡單、複雜SQL,在國內互聯網公司使用眾多。

本文針對筆者日常開發中對 Mybatis 返回集合類型是否需要判斷為 null 結合源碼,思考總結而來 - Mybatis 版本 3.5.11 - Spring boot 版本 3.0.1 - github地址:https://github.com/wayn111, 歡迎大家關注,點個star

一. 流程圖分析

直接給出博主梳理的調用流程圖,從用户dao方法執行開始,經過 MapperProxy 動態代理,對返回結果進行處理再到結束 未命名文件 (2).jpg 其中有幾個比較重要的類,我説明一下 - MapperMethod 對SQL執行類型進行判斷,判斷是insert、update、delete還是select類型,每個類型的處理流程都不一樣 - PrepareStatementHandler 對完成參數替換後的SQL語句執行數據庫查詢,返回ResultSet - DefaultResultHandler 對執行結果進行處理轉換

二. DefaultResultSetHandler對返回結果進行處理

MybatisResultSetHandler 接口用於在 StatementHandler 對象執行完查詢操作或存儲過程後,對結果集或存儲過程的執行結果進行處理。同理,當返回集合類型時,Mybatis 最後也會交給 ResultSetHandler 的實現類 DefaultResultSetHandler 來處理,最終在 handleResultSet() 方法中完成對返回集合類型的處理,如下圖

image.png

可以看出 Mybatis 先創建 DefaultResultHandler 對象,接着放入 handleRowValues() 方法中,該方法會把數據庫查詢返回的多條記錄轉換為 resultMap 對應的對象放入 defaultResultHandler,最後調用 defaultResultHandler.getResultList() 方法將結果放到最終返回需要的 multipleResults 中。multipleResults 對象中就包含了我們最終返回的集合對象,Mybatis 會從 multipleResults 中獲取第一個元素作為 MapperProxy 的返回結果

三. DefaultResultHandler一個包含實際要返回集合對象的處理類

在上面代碼中有一個非常重要的類,那就是 DefaultResultHandler 類,實際上我們返回的集合對象就是 DefaultResultHandler 內部的成員屬性 list ,查看源碼

image.png

  • 裏面有一個 list 成員屬性,該屬性在構造器中由objectFactory對象調用 create(List.class) 方法創建,進入其中

image.pngresolveInterface(type) 方法中,對傳入的類對象做具體轉換

image.png

可以看到 List.class 被轉換為 ArrayList.class,接着調用 instantiateClass() 方法,完成空集合的創建,(劃重點)由此可見,Mybatis 返回集合類型默認是空集合 - handlerResult(ResultContext<?> context) 方法,該方法會往 list 中添加元素

  • getResultList() 方法,直接返回list成員屬性

結合上面提到的最後調用 defaultResultHandler.getResultList() 方法將結果放到最終返回需要的 multipleResults 中,我們很容易就能知道,我們返回的集合對象實際上就是 DefaultResultHandler 類中的 list 屬性,然後我們重新梳理下上文中第二部分:

DefaultResultSetHandler對返回結果進行處理 1. 先創建 DefaultResultHandler 對象,初始化 list 成員屬性為空集合 2. 在 handleRowValues() 方法中,處理返回記錄,轉換為 resultMap 對應的對象類型,這個過程中,如果數據庫返回不為空,就會調用 DefaultResultHandler 類中的 handlerResult(ResultContext<?> context) 方法,將返回對象放入成員屬性 list 集合中 3. 調用 defaultResultHandler.getResultList() 方法,將成員屬性 list 集合放入multipleResults,這也就對應了上文提到的 multipleResults 對象中就包含了我們最終返回的集合對象

四. 總結

由上經過源碼分析,我們知道 Mybatis 返回集合類型默認是空集合,我們在日常開發中,對於 Mybatis 返回集合類型不需要判斷是否為 null,直接調用 list.size() > 0 或者其他第三方工具包提供的集合判空方法即可