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 或者其他第三方工具包提供的集合判空方法即可