原创

mybatis批量插入数据

首先mybatis新增插入一条数据,mapper.xml文件中可以这么写:

<insert id="testInsertData">
        insert into mybatis_insert_datas_test
            (value1,value2)
        values
             (#{value1},#{value2})
</insert>

mybatis批量插入数据,可以在mapper.xml配置文件新增编码如下:

<insert id="testInsertDatas">
        insert into mybatis_insert_datas_test
            (value1,value2)
        values
        <foreach collection="list" item="data" separator=",">
             (#{data.value1},#{data.value2})
        </foreach>
</insert>

其实上面的方法在数据少量的时候是可以的,数据量大(上万条甚至几十万条)的时候就会报错I/O error,因为上面的这种方式就是使用sql拼接来批量插入数据的,大量数据导致SQL语句过长从而导致了I/O的错误。
解决办法可以在Java代码中分批次插入,例如每次200条,这个根据自己服务器内存情况决定,自己测试一下就知道合理的范围。

public void batchInsertDatas(@PathVariable("dataNames") string dataNames) {
        // 获取数据
        List<BatchData> dataList = dataMapper.getDataList(dataNames);

        // 大数据分批处理入库
        List<List<BatchData>> dataGroups = ListUtil.splitList(dataList, 200);
        for (List<BatchData> group : dataGroup) {
            batchInsertMapper.insertDataList(group);
        }
}

还可以使用Batch Insert来批量插入,这种方法感觉很好用,拦截StatementHandler的prepare执行方法,可以看到只执行了一次预编译。批量插入不会出现参数个数超限或者SQL语句超长的问题。

mapper.xml配置文件也是单条一样

<insert id="testInsertData" useGeneratedKeys="true" keyProperty="data.id" keyColumn="id">
        insert into mybatis_insert_datas_test
            (value1,value2)
        values
             (#{data.value1},#{data.value2})
</insert>

主要是应用层代码实现

public void testInsertData(@PathVariable("dataNames") string dataNames) {
        SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH, false);

        try {
            BatchInsertMapper insertMapper = session.getMapper(BatchInsertMapper.class);

            // 获取数据
            List<BatchData> dataList = dataMapper.getDataList(dataNames);
            for (BatchData data : dataList) {
                insertMapper.testInsertData(data);
            }

            session.commit();
            session.clearCache();
        } catch (Exception e) {
            session.rollback();
        } finally {
            session.close();
        }
}

注意:虽然这种方法20万条数据插入十几秒就可以搞定,但是更大数据量的时候,还是要分批量比较好点,最好一次提交控制在2秒以内完成。

本文链接地址:http://www.ysxbohui.com/article/172

正文到此结束