首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

iBatis 處理二維 List 參數的動態 SQL 寫法詳解

     編輯:程式設計綜合問答

問題場景

參數為 List<List<String>> countryCodesList,結構如 [[US,ZH,XX],[ALL]]。需在 SQL 中遍歷二維列表,生成類似:

(authCountryCodes LIKE '%|US|%' AND authCountryCodes LIKE '%|ZH|%' AND authCountryCodes LIKE '%|XX|%')
OR (authCountryCodes LIKE '%|ALL|%')

嘗試使用 #countryCodesList[][]# 但報 NullPointerException。

根本原因

iBatis (MyBatis 2.x) 的 OGNL 表達式不支援直接雙重下標遍歷二維集合。#countryCodesList[][]# 會嘗試將整個二維列表當作單層迭代,導致參數映射失敗。

解決方案:在 Java 層扁平化或預處理

方案一:Service 層轉換為一維 List 傳入

// 原始二維列表
List<List<String>> countryCodesList = ...;
// 轉換為一維列表,並在元素前添加分組標識(可選)
List<String> flatList = new ArrayList<>();
for (List<String> group : countryCodesList) {
    for (String code : group) {
        flatList.add(code); // 或 "GROUP1:" + code
    }
}
// 傳入 flatList,SQL 中用 <iterate> 遍歷

方案二:使用 <iterate> 嵌套(需自定義 TypeHandler 或動態 SQL 技巧)

iBatis 不直接支援嵌套 iterate。建議改用 MyBatis 3.x,利用 <foreach> 支援嵌套集合:

<foreach collection="countryCodesList" item="group" separator="OR">
  (<foreach collection="group" item="code" separator="AND">
    authCountryCodes LIKE '%|#{code}|%'
  </foreach>)
</foreach>

方案三:構建動態 SQL 字串傳入(不推薦,有注入風險)

在 DAO 層手動拼接 SQL 片段,作為字串參數傳入 $sqlFragment$(注意:$ 為直接替換,需自行防注入)。

最佳實踐建議

  1. 升級到 MyBatis 3.x:原生支援集合嵌套遍歷,語法清晰安全。
  2. 參數預處理:在 Service 層將複雜結構轉換為簡單集合,SQL 保持簡單。
  3. 避免在 SQL 中實現複雜業務邏輯:動態 SQL 難維護、難測試,核心邏輯應在 Java 層完成。

錯誤堆疊分析

--- The error occurred while applying a parameter map.
--- Check the parameter mapping for the 'countryCodesList[0][0]' property.
--- Cause: java.lang.NullPointerException

確認是 OGNL 解析 [0][0] 時內部對象為空導致。

總結

iBatis 無法直接處理二維 List 參數。推薦升級 MyBatis 3.x 使用 <foreach> 嵌套,或在 Java 層扁平化數據結構後再傳入 SQL。切勿在 SQL 中硬編碼複雜遍歷邏輯。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved