| 屬性 | 必填 | 說明 | 示例 |
|---|---|---|---|
| collection | 是 | 要迭代的集合對象 (關鍵:值取決於參數類型) | list / array / mapKey |
| item | 是 | 迭代元素別名,在 #{item} 中引用 | id / item / logid |
| index | 否 | 索引別名 (List 為索引值,Map 為 Key) | index / idx |
| open | 否 | 迭代開始字符串 | ( |
| separator | 否 | 元素間分隔符 | , |
| close | 否 | 迭代結束字符串 | ) |
<!-- 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"。
<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"。
<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。
<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 限制。
<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> 判空,構建靈活查詢。
<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 found | collection 值與實際 Map Key 不匹配 | 檢查 @Param 值、單參數固定 Key (list/array)、Map 實際 Key |
| SQL 語法錯誤近 IN () | 集合為空導致生成 IN () | 外層加 <if test="list != null and list.size() > 0"> 判空 |
| 批量插入數據截斷 | 超過 max_allowed_packet | 分批提交 (如每 500 條) 或調大該參數 |
| #{item} 取值為 null | item 別名與實體屬性名不一致 | 確保 item 對應對象屬性,或用 #{item.property} 訪問嵌套屬性 |
SqlSessionFactory.openSession(ExecutorType.BATCH) 批量預編譯foreach 是 MyBatis 動態 SQL 中處理集合迭代的核心標籤。掌握 collection 值與參數類型的對應關係 是正確使用的關鍵:單參數 List 用 list、數組用 array、多參數 Map 用自定義 Key。結合 <where>/<if> 實現靈活條件構建,批量操作顯著提升性能。實戰中注意空集合保護與包大小限制,善用 BatchExecutor 處理大數據量場景。