版权声明:转载请注明出处哦 https://blog.csdn.net/k99sam/article/details/82253488
场景:
导入20万条数据,for循环方式一条条插入巨慢(太low)。拼接长SQL的话,oracle根本无法支持(有SQL长度限制),经测试数据多于2000基本就不行了。故改用批量插入,在mapper中注解使用mybatis的foreach标签写。Mybatis框架会自动拼接生成批插的sql。
mysql版(这里只写2个字段,大家自己照葫芦画瓢)
@Insert(
{ "<script>",
"insert into users ",
"(USERNAME,PASSWORD) ",
"VALUES",
"<foreach collection ='list' item='ulist' separator =','>",
"(#{ulist.username},#{ulist.password})",
"</foreach> ",
"</script>"
}
)
public void batch_insert(List<UserEntity> userList);
要点解析:
1. 注解的{} 中,长的SQL要换行的话,注意逗号和引号,每行内容在" "中。({}中内容是数组,这个好理解)
2. <foreach>标签中是循环拼接的语句,注意前后有(),字段务必在括号里
3. collection ='list' 标明传入的数据是list类型的(还有其他的,请参阅官方文档)
4. item值不必与形参名字相同,它的作用可以这么理解:形参的替身/别名,如下图:
5. separator =',' 说明要用什么来分隔两段语句(可以看oracle的例子,这里有什么不同)
最终拼接出来的语句如下(如果插入2行数据):
insert into users (username,password) values ('sam','123'),('tom','456');
oracle版:
@Insert(
{"<script>",
"insert into users ",
"(ID,username,password) ",
"SELECT SEQ_USERS.NEXTVAL, A.* FROM (",
"<foreach collection ='list' item='ulist' separator ='union all'>",
"(SELECT #{ulist.username},#{ulist.password} FROM DUAL)",
"</foreach> ) A",
"</script>"
}
)
public void batch_insert(List<UserEntity> userList);
比较复杂,使用了嵌套结构,多行语句之间使用union all连接。
特别注意,如果要插入序列,序列是要写在foreach外的。
实际运行测试:
使用oracle,每批2000条commit一次为最佳。
扫描二维码关注公众号,回复:
3970652 查看本文章
换用mysql,可以20000条再commit一次,且速度比oracle快多了(同一台机器测试)。