这篇文章主要对foreach里面的collection相关的内容做一些介绍,围绕foreach做一些数据插入和查询相关的研究
。
foreach属性
属性 | 描述 |
---|---|
item | 循环体中的具体对象。支持属性的点路径访问,如item.age,item.info.details。 具体说明:在list和数组中是其中的对象,在map中是value。 该参数为必选。 |
collection | 要做foreach的对象,作为入参时,List<?>对象默认用list代替作为键,数组对象有array代替作为键,Map对象没有默认的键。 当然在作为入参时可以使用@Param("keyName")来设置键,设置keyName后,list,array将会失效。 除了入参这种情况外,还有一种作为参数对象的某个字段的时候。举个例子: 如果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,该参数可选。 |
通过传入参数对foreach进行分类大体上能分为三种类型,分别为List,[](array),Map三种。
1.数据采用list传入
mapper的sql:
<insert id="foreachSelectKeyInsert" parameterType="java.util.List" useGeneratedKeys="true" keyProperty="id">
insert into demo_user (name, age) values
<foreach item="st" collection="list" index="idx" open="" separator="," close="">
(#{st.name, jdbcType=VARCHAR}, #{st.age, jdbcType=INTEGER})
</foreach>
</insert>
mapper接口:
void foreachSelectKeyInsert(List<UserEntity> list);
测试代码
@Autowired
UserMapper userMapper;
@Test
public void test1 (){
List<UserEntity> list = new ArrayList<>();
UserEntity user1 = new UserEntity();
user1.setAge(23);
user1.setName("小王");
list.add(user1);
UserEntity user2 = new UserEntity();
user2.setAge(24);
user2.setName("老王");
list.add(user2);
userMapper.foreachSelectKeyInsert(list);
}
测试结果:
2.数据采用Array传入
mapper的sql:
<select id="findByIds" parameterType="java.lang.Integer" resultType="com.example.demo.entity.UserEntity">
select * from demo_user
<where>
id in
<foreach item="item" collection="array" index="idx" open="(" separator="," close=")">
#{item, jdbcType=INTEGER}
</foreach>
</where>
</select>
mapper接口:
List<UserEntity> findByIds(Integer[] array);
测试方法:
@Test
public void test2 (){
Integer[] array = {1,2};
List<UserEntity> list = userMapper.findByIds(array);
for(UserEntity user : list){
System.out.println(user.toString());
}
}
测试结果:
3.数据采用Map传入
map和List,array相比,map是用K,V存储的,在foreach中,使用map时,index属性值为map中的Key的值。
因为map中的Key不同于list,array中的索引,所以会有更丰富的用法。
这里就介绍两种 mapper 中 sql 写法,mapper接口和测试都差不多就不写了。
<insert id="isnertUser">
insert into demo_user (key, value) values
<foreach item="item" index="key" collection="map" open="" separator="," close="">
(#{key}, #{item})
</foreach>
</insert>
通过map来实现动态条件查询,就不用再写那么多的<if>了,
一定要注意到$和#的区别
,$的参数直接输出,#的参数会被替换为?,然后传入参数值执行。
<select id="findByCon" resultType="int">
select count(1) from demo_user
<where>
<foreach item="item" index="key" collection="map" open="" separator="AND" close="">
${key} = #{item}
</foreach>
</where>
</select>
总结:
在使用foreach的时候最关键的也是最容易出错的就是collection属性,该属性是必须指定的,但是在不同情况下,该属性的值是不一样的,主要有一下3种情况:
1.如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
2.如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
- 3.如果传入的参数是多个的时候,我们就需要把它们封装成一个Map或者Object。