- 概述
- MyBatis 的
foreach
标签用于在 SQL 语句中遍历集合(如List
、Set
等)或数组,它提供了一种方便的方式来动态生成 SQL 片段,比如批量插入、批量更新或根据一组条件进行查询等操作。
- 基本语法结构
foreach
标签通常包含以下属性:
collection
:指定要遍历的集合或数组。这个属性的值可以是方法参数中的集合名称、Map
中的键(如果参数是Map
且集合作为值存储在Map
中)等。item
:表示集合或数组中的每个元素在遍历过程中的别名。在 SQL 语句中可以使用这个别名来引用元素。index
:可选属性,用于表示当前元素在集合或数组中的索引位置(对于数组和List
等有序集合),可以在 SQL 语句中使用这个索引。open
:可选属性,用于指定遍历开始时添加的 SQL 片段,比如在批量插入时可能是("INSERT INTO table (column1, column2) VALUES"
。close
:可选属性,用于指定遍历结束时添加的 SQL 片段,例如在批量插入时可能是)
。separator
:可选属性,用于指定每个元素之间的分隔符,在批量插入中可能是),(
,用于分隔每个VALUES
子句。
- 批量插入示例
- 假设我们有一个
List<User>
,其中User
是一个包含name
和age
属性的 Java 类,我们想将这些用户信息批量插入到数据库的user
表中。 - Mapper 接口方法定义可能如下:
void batchInsert(List<User> userList);
- Mapper XML 中的 SQL 语句可以这样写:
<insert id="batchInsert"> INSERT INTO user (name, age) VALUES <foreach collection="userList" item="user" separator=","> (#{user.name}, #{user.age}) </foreach> </insert>
- 在这个示例中:
collection
属性的值是userList
,这是传入方法的List<User>
的名称。item
属性的值是user
,表示userList
中的每个User
对象在 SQL 语句中可以用user
来指代。separator
属性的值是,
,用于在每个VALUES
子句之间添加逗号进行分隔。- 这样,MyBatis 会根据
userList
中的元素数量动态生成批量插入的 SQL 语句。
- 根据条件列表查询示例
- 假设我们有一个
List<Integer>
,其中包含用户 ID,我们想查询这些用户的信息。 - Mapper 接口方法定义:
List<User> findUsersByIdList(List<Integer> idList);
- Mapper XML 中的 SQL 语句:
<select id="findUsersByIdList"> SELECT * FROM user WHERE id IN <foreach collection="idList" item="id" open="(" close=")" separator=","> #{id} </foreach> </select>
- 在这里:
collection
属性的值是idList
,代表传入的包含用户 ID 的List
。item
属性是id
,用于在 SQL 语句中引用idList
中的每个 ID。open
和close
属性分别是(
和)
,用于包围IN
操作符后的条件列表。separator
属性是,
,用于分隔每个 ID,这样就可以正确地构建IN
条件查询的 SQL 语句。
- 遍历 Map 示例
- 如果参数是
Map
类型,并且Map
中包含集合作为值,foreach
标签也可以很好地工作。假设Map
的键是category
,值是List<Integer>
,表示每个类别下的产品 ID 列表,我们想查询每个类别下的产品。 - Mapper 接口方法定义:
List<Product> findProductsByCategory(Map<String, List<Integer>> categoryMap);
- Mapper XML 中的 SQL 语句:
<select id="findProductsByCategory"> SELECT * FROM product WHERE <foreach collection="categoryMap" item="idList" key="category"> (category = #{category} AND id IN <foreach collection="idList" item="id" open="(" close=")" separator=","> #{id} </foreach> ) OR </foreach> 1 = 0 </select>
- 在这个复杂的示例中:
- 外层
foreach
遍历categoryMap
,key
属性指定了Map
的键(category
)作为 SQL 语句中的一个条件,item
属性指定了Map
的值(idList
),这是一个包含产品 ID 的List
。 - 内层
foreach
用于遍历每个类别下的产品 ID 列表,构建IN
条件,和前面的IN
查询示例类似。 - 最后添加
1 = 0
是为了在最后一个OR
条件后使整个WHERE
语句语法正确,因为如果没有这个,最后一个OR
条件会导致语法错误。这是一种常用的技巧来确保 SQL 语句的正确性。