1、使用场景
在实际开发过程中,我们经常需要批量更新或者是批量查询,此时如果逐条插入,将影响效率。所以通常我们都是将其封装为一个集合,再进行插入。主要以下三种方式:
- foreach 实现批量插入
- foreach 实现in集合
- foreach 实现动态update,与插入类似。
- foreach优化
2、foreach属性介绍
- collection:指定要遍历的集合。入参为list,collection为list;入参为数组,collection为array;入参为map,collection为集合的名称;不过你写collection也可以。
- index:循环索引,遍历l数组或者集合时,该值为当前索引值;遍历map的时候index表示的就是map的key,item就是map的值。
- item:将当前遍历出的元素赋值给指定的变量,可以理解成变量中的user。
- open:循环以什么开始。
- close:循环以什么结束。
- separator:循环内容之间以什么分隔。
3、foreach实现insert批量插入
在此之前,要配置好maven环境,增加junit、log4j(便于调试测试)依赖,具体可以看我之前写的文章:https://blog.csdn.net/weixin_35798336/article/details/111052348
测试类:
@Test
public void insertsTest(){
List<User> users= new ArrayList<User>();
/*将user加入集合为了演示,实际项目中不可能出现该类重复代码*/
User user = new User(11,"as","sds",10);
User user1 = new User(12,"as","sds",0);
User user2 = new User(13,"as","sds",0);
User user3 = new User(14,"as","sds",0);
User user4 = new User(15,"as","sds",0);
users.add(user);
users.add(user1);
users.add(user2);
users.add(user3);
users.add(user4);
/*调用mapper接口*/
mapper.insertUsers(users);
sqlSession.commit();
}
接口方法:
int insertUsers(List<User> users);
xml映射文件:
<insert id="insertUsers">
insert into user (id , name ,password, `delete`) values
/*此处collection处一般按照实际类型填写,此处本应填写list,演示所用;item处即为下列中的user.id中的user。*/
/*insert into user (id , name ,password, `delete`) values (?,?,?,?) , (?,?,?,?) , (?,?,?,?) , (?,?,?,?) , (?,?,?,?),foreach中的代码即为values中要写的重复代码,separator就是每一次迭代中要增加的符号。*/
<foreach collection="collection" item="user" separator=",">
(#{user.id},#{user.name},#{user.password},#{user.delete})
</foreach>
</insert>
4、foreach 实现in集合
in集合一般使用的场景为客户或者系统运维人员需要拉取某批指定id的用户的数据,此时,我们需要用in。
java代码:
@Test
public void selectIdsTest(){
List<Integer> ids= new ArrayList<Integer>();
/*将user加入集合为了演示,实际项目中不可能出现该类重复代码*/
ids.add(12);
ids.add(13);
ids.add(14);
ids.add(15);
/*调用mapper接口*/
List<User> user = mapper.findAllByIds(ids);
for (User user1 : user) {
System.out.println(user);
}
sqlSession.commit();
}
List<User> findAllByIds(List<Integer> ids);//接口方法
<select id="findAllByIds" resultType="User">
/*这是要显示的语句:所以以open和close来做开始结束。select * from user where id in (11,12,13,14)*/
select * from user where id in
<foreach collection="list" item="ids" open ="(" close=")" separator=",">
#{ids}
</foreach>
</select>
4、优化,不同方式对于执行速度的影响(数据量大的情况)
就是以上代码的执行方法。
在代码中拼接字符串,作为参数传入配置文件中,在配置文件中将 通过
${xxx}来获取:<select id="findAllByIds" resultType="User"> select * from user <where> <if test="ids != null and ids != ''"> and id in ${ids} </if> </where> </select>在配置文件中 通过
#{xxx}来获取:代码与上面的类似,仅把${ids}修改为#{ids}。
总结:在数据量非常大的时候解析的速度为方式1<方式2<方式3。
简单来说foreach这么慢的原因是因为foreach实际上是把语句变成了:
select * from user where id in (#{__frch_item_0}, #{__frch_item_1}, #{__frch_item_2}, #{__frch_item_3}, #{__frch_item_4})
而关于#与$的区别,即两种符号其实分别对应的是jdbc中的PreparedStatment 对象和Statment 对象。当使用 Statement 对象时,每次执行一个SQL命令时,都会对它进行解析和编译。而PreparedStatment 表示预编译的SQL,包含的SQL已经预编译过了,SQL 中的参数部分使用 ?进行占位。所以之后的sql进行大数据的传入时,可以将数据分批拼接传入。
版权声明:本文为weixin_35798336原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。