mybatis的批量操作有两种方式,一是使用foreach标签,二是使用mybatis的BATCH模型
foreach标签
在xml中通过foreach对表数据进行循环操作
<insert id="insertProduct">
insert into product(name, type, price)
values
<foreache collection="list" item="item" separator=",">
( #{item.name}, #{item.type}, #{item.price})
</foreach>
</insert>
在oracle中不支持insert into product(name, type, price) values ('a', 'tv', 1233), ('b', 'ac', 3455),....('','','')这种形式的sql,因此oracle批量插入使用 insert all into table(...) values(...) into table(...) values(...) select * from dual; 语句来解决以下方式,并且需要显示指定useGeneratedKeys=false
<insert id="insertProduct parameterType="java.util.List" useGeneratedKeys="false">
insert all
<foreach collection="list" item="item" index="index">
into product(name, type, price)
values
(#{item.name}, #{item.type}, #{item.price})
</foreach>
select 1 from dual
</insert>
另一种方法是使用另外一种方法是 insert into table(...) (select ... from dual) union all (select ... from dual)
<insert id="insertProduct parameterType="java.util.List" useGeneratedKeys="false">
insert into product(name, type, price)
<foreach collection="list" item="item" index="index" separator="union all">
select
( #{item.name}, #{item.type}, #{item.price})
from dual
</foreach>
</insert>
ExecutorType.BATCH
Mybatis内置的ExecutorType一共有三种,默认为SIMPLE,该模式下它为每个语句的执行创建一个新的预处理语句,并单条提交sql。
而BATCH模式会重复使用已经预处理的语句,并且批量执行所有更新语句,显然batch性能将更优;
注意: batch模式也有自己的问题,比如在Insert操作时,在事务没有提交之前,是没有办法获取到自增的id,这在某型情形下是不符合业务要求的。
具体用法如下:
class Batch{
@Autowired
SqlSessionFactory sqlSessionFactory;
public void testBatch() {
//取得可以执行批量操作的SQLSession
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
//取到对应的mapper对象
ProductMapper mapper = sqlSession.getMapper(ProductMapper.class);
//添加批量数据到预处理语句中
for (int i=0; i<10000; i++) {
mapper.addProduct(new Product("aaa", "TV", 1234);
}
//提交session
sqlSession.commit();
//关闭session
sqlSession.close(); //可以放在final中
}
}
//批量 预编译sql一次==》设置参数==》10000次==》执行1次
//非批量 (预编译=设置参数=执行 )==》10000次
ProductMapper.java如下:
class ProductMapper{
public long addProduct(Product product);
}
mapper.xml如下:
<mapper>
<insert id="addProduct" parameterType="xxx.xxx.Product">
insert into Product(name, type, price)
values
(#{name, jdbcType=VARCHAR}, #{type, jdbcType=VARCHAR}, #{price, jdbcType=NUMBER})
</insert>
<mapper>