foreach属性

  • item
    循环体中的具体对象。支持属性的点路径访问,如item.age,item.info.details。
    具体说明:在list和数组中是其中的对象,在map中是value。
    该参数为必选。

  • collection
    要做foreach的对象,作为入参时,List<?>对象默认用list代替作为键,数组对象有array代替作为键,Map对象用map代替作为键。
    当然在作为入参时可以使用@Param(“keyName”)来设置键,设置keyName后,list,array,map将会失效。 除了入参这种情况外,还有一种作为参数对象的某个字段的时候。举个例子:
    如果User有属性List ids。入参是User对象,那么这个collection = “ids”
    如果User有属性Ids ids;其中Ids是个对象,Ids有个属性List id;入参是User对象,那么collection = “ids.id”
    上面只是举例,具体collection等于什么,就看你想对那个元素做循环。
    该参数为必选。

  • separator
    元素之间的分隔符,例如在in()的时候,separator=”,”会自动在元素中间用“,“隔开,避免手动输入逗号导致sql错误,如in(1,2,)这样。该参数可选。

  • open
    foreach代码的开始符号,一般是(和close=”)”合用。常用在in(),values()时。该参数可选。

  • close
    foreach代码的关闭符号,一般是)和open=”(“合用。常用在in(),values()时。该参数可选。

  • index
    在list和数组中,index是元素的序号,在map中,index是元素的key,该参数可选。

举例

实现 xx in ()

1
2
3
4
5
6
7
8
9
<select id="countByUserList" resultType="int" parameterType="list">  
select * from t_user  
  <where>  
    id in  
    <foreach item="item" collection="list" separator="," open="(" close=")" index="">  
      #{item.id, jdbcType=NUMERIC}  
    </foreach>  
  </where>  
</select>

sql效果:

1
select * from t_user WHERE id in ( ? , ? )

批量插入数据(参数List)

SQL效果:

1
insert into t_user select ?,? from dual union all select ?,? from dual

1
2
3
4
5
6
7
8
9
10
11
12
<insert id="addUserList">
    INSERT INTO DELIVER
        (
            id,name
         )
      <foreach collection="userList" item="item" separator="UNION ALL">
            SELECT 
                 #{item.id, jdbcType=NUMERIC},
                 #{item.name, jdbcType=VARCHAR}
            FROM DUAL
      </foreach>
</insert>

批量插入数据(参数Map)

sql:

1
insert into t_user (key, value) values (?, ?) , (?, ?)

1
2
3
4
5
<insert id="batchSaveUser">  
    insert into t_user (key, value) values  
    <foreach item="item" index="key" collection="map"  
        open="" separator="," close="">(#{key}, #{item})</foreach>  
</insert>

其中Map的key是列名,value是字段值。

动态查询数据(根据列名不同)

1
2
3
4
5
<select id="dynamicQuery" resultType="int">  
    select count(*) from t_user where  
    <foreach item="item" index="key" collection="map"  
        open="" separator="AND" close="">${key} = #{item}</foreach>  
</select>

一定要注意到$和#的区别,$的参数直接输出,#的参数会被替换为?,然后传入参数值执行。

批量插入数据(List参数)

示例参数:List<Map<String,Object>>

这里想实现的功能是批量插入数据。生成的SQL如下:

1
insert into sys_outpatient_his(sys_id,his_id,is_receive,gmt_create) values (?,?,?),(?,?,?),(?,?,?)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
List<Map<String, Object>> items = new ArrayList<>();
        
Long sysId = 1L;
Long hisId = 0L;
short isReceive = 0;

for (int i=0;i<3;i++) {
    isReceive = (short) (i == 1 ? 1:0);
    hisId = (long) (i+1);
    
    Map<String, Object> param = new HashMap<>(4);
    param.put("sysId", sysId);
    param.put("hisId", hisId);
    param.put("isReceive", isReceive);
    items.add(param);
}

this.dao.batchSaveSysAndHisRelation(items);

Mapper类:

1
void batchSaveSysAndHisRelation(@Param("params") List<Map<String,Object>> params);

mybatis xml:

1
2
3
4
5
6
7
<insert id="batchSaveSysAndHisRelation">
    insert into sys_outpatient_his(sys_id,his_id,is_receive,gmt_create) values
    <foreach item="his" index="i" collection="params" open="" close="" separator=",">
    (#{his.sysId},#{his.hisId},#{his.isReceive},now())
    </foreach>
        
</insert>

遍历Map参数

这里想实现的是根据sysId和hisIds删除数据,其中hisIds是要给数组。
SQL如下:

1
delete from sys_outpatient_his where sys_id = ? and his_id in ( ? , ? , ? )

调用代码:

1
2
3
4
5
6
7
Map<String,Object> params = new HashMap(2);

params.put("sysId", 1L);
Long[] ids = {1L,2L,3L};
params.put("hisIds", ids);

this.dao.batchRemoveSysAndHisRelation(params);

Mapper:

1
void batchRemoveSysAndHisRelation(@Param("params") Map<String,Object> params);

mybatis xml:

1
2
3
4
5
6
7
<delete id="batchRemoveSysAndHisRelation" parameterType="map">
delete from sys_outpatient_his where sys_id = #{params.sysId}
    and his_id in 
    <foreach item="hisId" collection="params.hisIds" open="(" close=")" separator=",">
    #{hisId}
    </foreach>
</delete>

判断参数是否存在

1
2
3
<if test="params.containsKey('sysId')">
    AND sysId = #{sysId,jdbcType=VARCHAR})
</if>

如果不指定参数:

1
2
3
<if test="_parameter.containsKey('sysId')">
    AND sysId = #{sysId,jdbcType=VARCHAR})
</if>

参考:https://blog.csdn.net/wangyangbto/article/details/18049131https://blog.csdn.net/jason5186/article/details/40896043

foreach嵌套

参考:https://blog.csdn.net/bidelinqi12/article/details/53121279