MyBatis批量插入大量数据(1w以上)

 更新时间:2022年01月05日 15:32:05   作者:xlecho  
MyBatis进行批量插入数时,一次性插入超过一千条的时候MyBatis开始报错,本文主要介绍了MyBatis批量插入大量数据的解决方法,感兴趣的可以了解一下

问题背景:只用MyBatis中foreach进行批量插入数据,一次性插入超过一千条的时候MyBatis开始报错。项目使用技术:SpringBoot、MyBatis

批量插入碰到的问题:

java.lang.StackOverflowError: null

该问题是由于一次性插入数据1w条引起的,具体插入代码如下:

userDao.batchInsert(list);

<insert id="batchInsert" parameterType="java.util.List">
    INSERT INTO USER
    <trim prefix="(" suffix=")" suffixOverrides=",">
        ID, AGE, NAME, EMAIL
    </trim>
    SELECT A.*
    FROM
    (<foreach collection="list" index="index" item="item" separator="UNION ALL">
    SELECT
    sys_guid(), #{user.age}, #{user.name}, #{user.email}
    FROM dual
</foreach>) A
</insert>

以上的插入代码其实也是一种批量插入的方式,但是他的灵界点并不高,插入数据过多的时候,可能需要我们使用代码在一次分批。当然如果插入数据不超过5000的时候可以直接这么使用

插入1w条数据,发现出现错误,原因是数据量过大,栈内存溢出了。mybatis中直接使用foreach插入数据,就相当于将所有的sql预先拼接到一起,然后一起提交。这本身就是一种批量插入的处理方案,但是达不到我们要求。主要是插入有上限。如果需要更多的数据导入,我们需要更换一种方式来解决这个问题,mybatis中ExecutorType的使用。

mybatis中ExecutorType的使用

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

插入大量数据的解决方案,使用ExecutorType

为了能够高效,并且解决上述问题,我们使用ExecutorType,并分批插入。代码如下:

//我们使用的是springboot,sqlSessionTemplate是可以自己注入的
@Autowired
private SqlSessionTemplate sqlSessionTemplate;

public void insertExcelData(List<User> list) {
    //如果自动提交设置为true,将无法控制提交的条数,改为最后统一提交,可能导致内存溢出
    SqlSession session = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false);
    //不自动提交
    try {
        UserDao userDao = session.getMapper(UserDao.class);
        for (int i = 0; i < list.size(); i++) {
            userDao.insert(list.get(i));
            if (i % 400 == 0 || i == list.size() - 1) {
                //手动每400条提交一次,提交后无法回滚
                session.commit();
                //清理缓存,防止溢出
                session.clearCache();
            }
        }
    } catch (Exception e) {
        //没有提交的数据可以回滚
        session.rollback();
    } finally {
        session.close();
    }
}

userDao.insert(User user);

<insert id="insert" parameterType="com.echo.UserPo">
    insert into USER
    (id
    <if test="age != null">
        ,age
    </if>
    <if test="name != null">
        ,name
    </if>
    <if test="email != null">
        ,email
    </if>
    )
    values (
    sys_guid()
    <if test="age != null">
        ,#{age}
    </if>
    <if test="name != null">
        ,#{name}
    </if>
    <if test="email != null">
        ,#{email}
    </if>)
</insert>

这里采用的是单条插入,直接使用for循环,但是使用ExecutorType.BACTH就相当于手动提交。这也是我们需要的效果,所以我们在循环里面判断了,是否到了第400笔,如果到了第400笔就直接提交,然后清空缓存,防止溢出。这样就有效的实现了批量插入,同时保证溢出问题的不出现

到此这篇关于MyBatis批量插入大量数据(1w以上)的文章就介绍到这了,更多相关MyBatis批量插入内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java序列化机制详解

    Java序列化机制详解

    Java 序列化机制是一种将对象转换为字节流的过程,以便在网络上传输或保存到文件中,并能在需要时将字节流还原为对象,这一机制通过实现 java.io.Serializable 接口来实现,同时涉及到一些关键概念和注意事项,需要的朋友可以参考下
    2023-12-12
  • 解决rocketmq-client查询手动发送消息异常问题

    解决rocketmq-client查询手动发送消息异常问题

    这篇文章主要介绍了解决rocketmq-client查询手动发送消息异常问题,具有很好的参考价值,希望对大家大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-08-08
  • Java中获取List中最后一个元素的三种方法

    Java中获取List中最后一个元素的三种方法

    在Java编程中我们经常需要获取一个List集合中的最后一个元素,这篇文章主要给大家介绍了关于Java中获取List中最后一个元素的三种方法,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2023-12-12
  • 将一个数组按照固定大小进行拆分成数组的方法

    将一个数组按照固定大小进行拆分成数组的方法

    下面小编就为大家带来一篇将一个数组按照固定大小进行拆分成数组的方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-11-11
  • Java中前端传参含有“+”“=”等特殊字符处理方式

    Java中前端传参含有“+”“=”等特殊字符处理方式

    这篇文章主要介绍了Java中前端传参含有“+”“=”等特殊字符处理,比如“+”如果不经过处理,传到Java后台之后,就变成空格了,“=”就直接没了,本文对这一问题给大家详细讲解,需要的朋友可以参考下
    2023-10-10
  • 基于java语言实现快递系统

    基于java语言实现快递系统

    这篇文章主要为大家详细介绍了基于java语言实现快递系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • Java中volatile关键字的作用是什么举例详解

    Java中volatile关键字的作用是什么举例详解

    这篇文章主要介绍了Java中volatile关键字的作用是什么的相关资料,volatile关键字在Java中用于修饰变量,提供可见性和禁止指令重排的特性,但不保证原子性,它通过内存屏障实现这些特性,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-04-04
  • IntelliJ IDEA下载GitHub私有仓库到本地的方法(新版)

    IntelliJ IDEA下载GitHub私有仓库到本地的方法(新版)

    这篇文章主要介绍了IntelliJ IDEA下载GitHub私有仓库到本地(新版),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-05-05
  • 深度解析Spring Filter方法示例

    深度解析Spring Filter方法示例

    这篇文章主要为大家介绍了深度解析Spring Filter用法示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08
  • 关于mybatis一对一查询一对多查询遇到的问题

    关于mybatis一对一查询一对多查询遇到的问题

    这篇文章主要介绍了关于mybatis一对一查询,一对多查询遇到的错误,接下来是对文章进行操作,要求查询全部文章,并关联查询作者,文章标签,本文给大家介绍的非常详细,需要的朋友可以参考下
    2022-05-05

最新评论