Mybatis批处理
第一种 单条SQL循环操作
1.Mapper.xml
```
<insert id="insert" parameterType="com.example.mybatisbatch.entity.OrderDetail">
insert into order_detail values
(#{order.id},#{order.name},#{order.phone},#{order.expressNo},#{order.productName},#{order.createTime})
</insert>
```
2.单元测试
```
/**
* 执行10000条
* for循环单条数据
* 耗时:共计:146秒
* insert执行完成,共计:146秒
* */
@Test
public void insertTest(){
List<OrderDetail> grenate = this.grenate(10000);
long start = System.currentTimeMillis();
grenate.forEach(x->{
orderDetailService.insert(x);
});
log.info("insert执行完成,共计:{}秒",(System.currentTimeMillis()-start)/1000);
}
```

第二种 XML中foreach批量操作
局限性:如果数据在200w XML是无法使用的,而且拼接容易出错,数据量小情况比第一种效率高。
1.Mapper
<insert id="insertBatch" parameterType="com.example.mybatisbatch.entity.OrderDetail">
insert into order_detail values
<foreach collection="list" separator="," item="order">
(#{order.id},#{order.name},#{order.phone},#{order.expressNo},#{order.productName},#{order.createTime})
</foreach>
</insert>
2.单元测试
/**
* XML foreach 执行10000
* 耗时:共计:4秒
* insertBatchTest执行完成,共计:4秒
* */
@Test
public void insertBatchTest(){
List<OrderDetail> grenate = this.grenate(10000);
long start = System.currentTimeMillis();
orderDetailService.insertBatch(grenate);
log.info("insertBatchTest执行完成,共计:{}秒",(System.currentTimeMillis()-start)/1000);
}

Mybatis BATCH 模式
⚠️:使用该模式必须rewriteBatchedStatements =true 在YML中Mysql链接URL中加入,原因是mysql jdbc默认无视executeBatch()语句,会把组成一组sql一句一条一条给Mysql执行,故性能下降。开启JDBC才会批量执行,对INSERT/UPDATE/DELETE有效。
1.复用第一种insert,使用满足1000条提交一次Commit 防止大数据内存溢出
```
@Override
public void mybatisBatch(List<OrderDetail> saveList) {
//打开批处理
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false);
OrderDetailMapper mapper = sqlSession.getMapper(OrderDetailMapper.class);
//1000提交一次 大数据量情况下防止内存溢出
for(int i=0;i<=saveList.size()-1;i++){
mapper.insert(saveList.get(i));
if(i%999 == 0){
sqlSession.commit();
sqlSession.clearCache();
}
}
sqlSession.commit();
sqlSession.clearCache();
}
```
2.单元测试性能
```
/**
* 复用 mappr insert方法
* 耗时:81秒 未开启rewriteBatchedStatements
* 耗时:3秒 开启rewriteBatchedStatements*/
@Test
public void mybatisBatchTest(){
List<OrderDetail> grenate = this.grenate(10000);
long start = System.currentTimeMillis();
orderDetailService.mybatisBatch(grenate);
log.info("mybatisBatchTest执行完成,共计:{}秒",(System.currentTimeMillis()-start)/1000);
}
```

总结
单条insert | XML中foreach | Mybatis BATCH | 操作条数 |
---|
146S | 4S | 3S | 1W |
补充
代码中功能生成数据 贴下
/**
* 生成10000条数据
* */
public List<OrderDetail> grenate(int index){
List<OrderDetail> result=new ArrayList<>();
for(int i=1;i<=index;i++){
result.add(OrderDetail.builder().createTime(LocalDateTime.now()).name("test"+i)
.phone(String.valueOf(i)).productName("商品"+i).expressNo(UUID.randomUUID().toString().replaceAll("-", "")).build());
}
return result;
}