天天看點

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

作者:java小悠
Mybatis 作為國内開發中常用到的半自動 orm 架構,相信大家都很熟悉,它提供了簡單靈活的xml映射配置,友善開發人員編寫簡單、複雜SQL,在國内網際網路公司使用衆多。

本文針對筆者日常開發中對 Mybatis 傳回集合類型是否需要判斷為 null 結合源碼,思考總結而來

  • Mybatis 版本 3.5.11
  • Spring boot 版本 3.0.1
  • github位址:github.com/wayn111

一. 流程圖分析

直接給出部落客梳理的調用流程圖,從使用者dao方法執行開始,經過 MapperProxy 動态代理,對傳回結果進行處理再到結束

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

其中有幾個比較重要的類,我說明一下

  • MapperMethod 對SQL執行類型進行判斷,判斷是insert、update、delete還是select類型,每個類型的處理流程都不一樣
  • PrepareStatementHandler 對完成參數替換後的SQL語句執行資料庫查詢,傳回ResultSet
  • DefaultResultHandler 對執行結果進行處理轉換

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

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

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

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

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

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

Mybatis傳回集合類型到底是空集合還是null?源碼解讀
  • 裡面有一個 list 成員屬性,該屬性在構造器中由objectFactory對象調用 create(List.class) 方法建立,進入其中
Mybatis傳回集合類型到底是空集合還是null?源碼解讀

在 resolveInterface(type) 方法中,對傳入的類對象做具體轉換

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

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

原文連結:https://juejin.cn/post/7188878848228851769

繼續閱讀