MyBatis foreach 标签
备注:本文修改于2022年6月28日。
1、MyBatis foreach 标签介绍
foreach 标签主要用在构建 in 条件中,它可以在 SQL 语句中遍历一个集合。
2、MyBatis foreach 标签属性
foreach 标签的属性主要有 collection,item,index,open,separator,close。其含义如下所示:
- collection:遍历的对象。当遍历对象是List、Array对象时,collection属性值分别默认用"list"、"array"代替,而Map对象没有默认的属性值。
注意:可以使用 @Param(“keyName”) 注解来自定义collection属性值,设置keyName后,list、array会失效。
- item:集合元素遍历时的别名称。该参数为必选项。
- index:在list、array中,index为元素的序号索引,但是在Map中,index为遍历元素的key值。该参数为可选项。
- open:遍历集合时的开始符号,通常与
close=")"
搭配使用。使用场景为IN()
、values()
时。该参数为可选项。 - separator:元素之间的分隔符,类比在
IN()
的时候,separator=","
,最终所有遍历的元素将会以设定的逗号符号隔开。该参数为可选项。 - close:遍历集合时的结束符号,通常与
open="("
搭配使用。该参数为可选项。
3、collection 属性值的三种情况
如果参数类型为List时,collection的默认属性值为list,同样可以使用@Param注解自定义;
如果参数类型为Array时,collection的默认属性值为array,同样可以使用@Param注解自定义;
如果传入的参数类型为Map时,collection的属性值可为下面三种情况:
- 遍历
map.keys
- 遍历
map.values
- 遍历
map.entrySet()
3.1 参数类型为 List,collection 属性值为 list
Mapper文件:
public List<User> selectByIds(List<Integer> userIds);
SQL片段:
<select id="selectByIds" resultType="cn.mybatis.domain.User">
select * from t_users where id in
<foreach collection="list" index="index" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</select>
3.2 参数类型为 List,使用 @Param 注解自定义 collection 属性值
Mapper文件:
List<UserList> getUserInfo(@Param("userName") List<String> userName);
SQL片段:
<select id="getUserInfo" resultType="cn.mybatis.domain.User">
SELECT * FROM t_users where
<if test="userName!= null and userName.size() >0">
USERNAME IN
<foreach collection="userName" item="value" separator="," open="(" close=")">
#{value}
</foreach>
</if>
</select>
3.3 参数类型为 Array,collection 属性值为 array
Mapper文件:
public List<User> selectByIds(int[] userIds);
SQL片段:
<select id="selectByIds" resultType="cn.mybatis.domain.User">
select * from t_user where id in
<foreach collection="array" index="index" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</select>
3.3 参数类型为 Array,使用 @Param 注解自定义 collection 属性值
Mapper文件:
List<UserList> getUserInfo(@Param("userName") String[] userName);
SQL片段:
<select id="getUserInfo" resultType="cn.mybatis.domain.User">
SELECT * FROM t_users where
<if test="userName!= null and userName.length() >0">
USERNAME IN
<foreach collection="userName" item="value" separator="," open="(" close=")">
#{value}
</foreach>
</if>
</select>
3.3 参数类型为 Map,collection 属性值分为三种情况
Mapper文件:
List<UserList> getUserInfo(@Param("user") Map<String,String> user);
第一种情况:获取Map的键值对
多字段组合条件情况下,一定要注意书写格式:括号()
<select id="getUserInfo" resultType="cn.mybatis.domain.User">
SELECT * FROM t_users where
<if test="user!= null and user.size() >0">
(USERNAME,AGE) IN
<foreach collection="user.entrySet()" item="value" index="key" separator="," open="(" close=")">
(#{key},#{value})
</foreach>
</if>
</select>
第二种:参数Map类型,只需要获取key值或者value值
<select id="getUserInfo" resultType="cn.mybatis.domain.User">
SELECT * FROM t_users where
<if test="user!= null and user.size() >0">
(USERNAME) IN
<foreach collection="user.keys" item="key" separator="," open="(" close=")">
#{key}
</foreach>
</if>
</select>
第三种:参数Map类型,只需要获取value值
<select id="getUserInfo" resultType="cn.mybatis.domain.User">
SELECT * FROM t_users where
<if test="user!= null and user.size() >0">
(USERNAME) IN
<foreach collection="user.values" item="value" separator="," open="(" close=")">
#{key}
</foreach>
</if>
</select>
4、补充介绍
关于动态SQL另外一个常用的操作就是需要对一个集合进行遍历,通常发生在构建IN条件语句时。
<select id="selectEmployeeIn" resultType="cn.mybatis.domain.Employee">
SELECT * FROM tb_employee WHERE ID in
<foreach item="item" index="index" collection="list" open="(" separator="," close=") ">
#{item}
</foreach>
</select>
foreach元素的功能非常强大,它允许指定一个集合,声明可以用在元素体内的集合项和索引变量。它也允许指定开闭匹配的字符串以及在迭代中间放置分隔符。这个元素是很智能的,因此它不会随机地附加多余的分隔符。
// 根据传入的id集合查询员工
List<Employee> selectEmployeeIn(List<Integer> ids);
selectEmployeeIn方法传入的参数是一个List集合,该集合中的每一个Integer元素表示需要查询的员工的id。
public void testSelectEmployeeIn(SqlSession session)
{
EmployeeMapper em = session.getMapper(EmployeeMapper.class);
// 创建List集合
List<Integer> ids = new Arraylist<Integer>();
// 往List集合中添加两个测试数据
ids.add(1);
ids.add(2);
List<Employee> list = em.selectEmployeeIn(ids);
list.forEach(employee -> System.out.println(employee));
}
测试selectEmployeeln方法,控制台显示如下:
DEBUG [main]==> Preparing: SELECT * FROM tb employee WHERE ID in( ? , ? )
DEBUG [main]==> Parameters: 1(Integer) , 2 (Integer)
DEBUG [main]<== Total: 2
Employee [id=1,loginname=jack,password=123456,name=杰克,sex=男,age=26,phone=13902019999,sal=9800.0,state=ACTIVE]
Employee [id=2,loginname=rose,password=123456,namem露丝,sex=女,age=21,phone=13902018888,sal=6800.0,state=ACTIVE]
可以看到,执行的sql语句是一个in条件语句,返回的是List集合中的id的员工数据。
利用mybatis的foreach批量新增,入库的顺序一定是入参List中对象的顺序么
是的。list是有序集合,底层利用list拼接sql的时候肯定是顺序的。