备注:本文修改于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的员工数据。

标签: none

已有 2 条评论

  1. think think

    利用mybatis的foreach批量新增,入库的顺序一定是入参List中对象的顺序么

    1. 是的。list是有序集合,底层利用list拼接sql的时候肯定是顺序的。

添加新评论