首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

MyBatis foreach 標籤深度解析與三大使用場景

     編輯:Java 相關知識

foreach 核心屬性

屬性必填說明示例
collection是要迭代的集合對象 (關鍵:值取決於參數類型)list / array / mapKey
item是迭代元素別名,在 #{item} 中引用id / item / logid
index否索引別名 (List 為索引值,Map 為 Key)index / idx
open否迭代開始字符串(
separator否元素間分隔符,
close否迭代結束字符串)

三大參數類型對應規則 (collection 值決定)

場景一:單參數 List 集合 → collection="list"

<!-- Mapper XML -->
<select id="selectByIds" resultType="Blog">
    SELECT * FROM blog WHERE id IN
    <foreach collection="list" item="id" open="(" separator="," close=")">
        #{id}
    </foreach>
</select>
// Mapper 接口
List<Blog> selectByIds(List<Integer> ids);
// 測試調用
List<Integer> ids = Arrays.asList(1, 3, 6);
mapper.selectByIds(ids);

原理:MyBatis 自動將單參數 List 包裝為 Map<String, Object>,Key 固定為 "list"。

場景二:單參數數組 → collection="array"

<select id="selectByArray" resultType="Blog">
    SELECT * FROM blog WHERE id IN
    <foreach collection="array" item="id" open="(" separator="," close=")">
        #{id}
    </foreach>
</select>
// Mapper 接口
List<Blog> selectByArray(int[] ids);
// 測試調用
int[] ids = {1, 3, 6, 9};
mapper.selectByArray(ids);

單參數數組自動包裝 Key 為 "array"。

場景三:多參數/自定義 Map → collection="map中的Key"

<select id="selectComplex" resultType="Blog">
    SELECT * FROM blog 
    WHERE title LIKE CONCAT('%', #{title}, '%')
    AND id IN
    <foreach collection="ids" item="id" open="(" separator="," close=")">
        #{id}
    </foreach>
</select>
// Mapper 接口
List<Blog> selectComplex(Map<String, Object> params);
// 調用構造
Map<String, Object> params = new HashMap<>();
params.put("ids", Arrays.asList(1,2,3,6,7,9));  // Key: "ids"
params.put("title", "MyBatis");
mapper.selectComplex(params);

通用規律:多參數時 MyBatis 自動封裝為 Map,Key 為 @Param 值或參數名 (如 param1/param2),collection 填寫對應的 Map Key。

進階用法與技巧

1. 批量插入 (Batch Insert)

<insert id="batchInsert" parameterType="map">
    INSERT INTO blog (title, author, create_time) VALUES
    <foreach collection="list" item="blog" separator=",">
        (#{blog.title}, #{blog.author}, NOW())
    </foreach>
</insert>

單條 SQL 批量插入,性能遠優於循環執行。注意 MySQL max_allowed_packet 限制。

2. 動態 WHERE 條件構建

<select id="dynamicQuery" resultType="Blog">
    SELECT * FROM blog
    <where>
        <if test="title != null"> title LIKE #{title} </if>
        <if test="ids != null and ids.size() > 0">
            AND id IN
            <foreach collection="ids" item="id" open="(" separator="," close=")"> #{id} </foreach>
        </if>
    </where>
</select>

結合 <where> 自動處理 AND/OR 前綴,<if> 判空,構建靈活查詢。

3. 更新多條記錄

<update id="batchUpdateStatus">
    UPDATE blog SET status = 1 WHERE id IN
    <foreach collection="list" item="id" open="(" separator="," close=")">
        #{id}
    </foreach>
</update>

常見錯誤與避坑指南

錯誤現象原因修正
BindingException: Parameter 'xxx' not foundcollection 值與實際 Map Key 不匹配檢查 @Param 值、單參數固定 Key (list/array)、Map 實際 Key
SQL 語法錯誤近 IN ()集合為空導致生成 IN ()外層加 <if test="list != null and list.size() > 0"> 判空
批量插入數據截斷超過 max_allowed_packet分批提交 (如每 500 條) 或調大該參數
#{item} 取值為 nullitem 別名與實體屬性名不一致確保 item 對應對象屬性,或用 #{item.property} 訪問嵌套屬性

性能優化建議

  • 適度分批:單次 IN 條目建議 < 1000,超過拆分多條 SQL 或使用臨時表
  • 索引覆蓋:IN 字段建立索引,避免全表掃描
  • 批量操作用 EXECUTOR_TYPE.BATCH:MyBatis SqlSessionFactory.openSession(ExecutorType.BATCH) 批量預編譯
  • 避免在循環中調用 Mapper:改用 foreach 批量 SQL 或 BatchExecutor

總結

foreach 是 MyBatis 動態 SQL 中處理集合迭代的核心標籤。掌握 collection 值與參數類型的對應關係 是正確使用的關鍵:單參數 List 用 list、數組用 array、多參數 Map 用自定義 Key。結合 <where>/<if> 實現靈活條件構建,批量操作顯著提升性能。實戰中注意空集合保護與包大小限制,善用 BatchExecutor 處理大數據量場景。

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