myBatis 三种批量写数据方式

416 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第5天,点击查看活动详情

一、环境

数据库使用的是mysqljdk是1.8,三种批量写入数据的方式为

  1. 反复执行单条插入语句

此方式简单方便,一个forEach循环搞定(本文章使用得是tkMyBatis的接口方法),如果数据量较小(20条数据左右)可使用循环insert单挑数据的方式,简单方便一个for循环就实现,但是多次与数据库进行交互,个人不建议使用。

//循环插入
@Transactional
public void add2(List<Item> itemList) {
    itemList.forEach(itemMapper::insertSelective);
  }
  1. xml拼接sql

在xml中使用标签生成sql语句,然后交由mybatis执行

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.insert.dao.ItemMapper">
    <insert id="insertByBatch">
        INSERT INTO tb_item VALUES
        <foreach collection="list" item="item" index="index" separator=",">
            (#{item.id},#{item.name}
        </foreach>
    </insert>
</mapper>
  1. 批处理执行

Mybatis内置的ExecutorType有3种,默认的是simple,该模式下它为每个语句的执行创建一个新的预处理语句,单条提交sql;而batch模式重复使用已经预处理的语句,并且批量执行所有更新语句,显然batch性能将更优; 但batch模式也有自己的问题,比如在Insert操作时,在事务没有提交之前,是没有办法获取到自增的id,这在某型情形下是不符合业务要求

@Service
public class ItemService {
    @Autowired
    private ItemMapper itemMapper;
    @Autowired
    private SqlSessionFactory sqlSessionFactory;
    //批处理
    @Transactional
    public void add(List<Item> itemList) {
        SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH,false);
        ItemMapper mapper = session.getMapper(ItemMapper.class);
        for (int i = ; i < itemList.size(); i++) {
            mapper.insertSelective(itemList.get(i));
            if(i%1000==999){//每1000条提交一次防止内存溢出
                session.commit();
                session.clearCache();
            }
        }
        session.commit();
        session.clearCache();
    }
    //通过拼接sql方式
    @Transactional
    public void add1(List<Item> itemList) {
        itemMapper.insertByBatch(itemList);
    }
    //循环插入方式
    @Transactional
    public void add2(List<Item> itemList) {
        itemList.forEach(itemMapper::insertSelective);
    }
}