开发者社区> 问答> 正文

mybaits 有选择的批量插入怎么写?:报错

mybaits 版本:3.2.8

tomcat 版本:7

先看单个动态插入:

其中:Selective_Value_List


Selective_Column_List如下:

这样就动态的拼接不为空的key和value了。

我想问批量动态的插入怎么写?

下面是我按照单个插入的思路写的。不行。报错呢


展开
收起
kun坤 2020-06-14 08:32:03 536 0
1 条回答
写回答
取消 提交回答
  • 批量插入碰到的问题: java.lang.StackOverflowError: null 1 该问题是由于一次性插入数据1w条引起的,具体插入代码如下:

    userDao.batchInsert(list);

    INSERT INTO USER ID, AGE, NAME, EMAIL SELECT A.* FROM ( SELECT sys_guid(), #{user.age}, #{user.name}, #{user.email} FROM dual ) A 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 以上的插入代码其实也是一种批量插入的方式,但是他的灵界点并不高,插入数据过多的时候,可能需要我们使用代码在一次分批。当然如果插入数据不超过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 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 into USER (id ,age ,name ,email ) values ( sys_guid() ,#{age} ,#{name} ,#{email} ) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 这里采用的是单条插入,直接使用for循环,但是使用ExecutorType.BACTH就相当于手动提交。这也是我们需要的效果,所以我们在循环里面判断了,是否到了第400笔,如果到了第400笔就直接提交,然后清空缓存,防止溢出。这样就有效的实现了批量插入,同时保证溢出问题的不出现

    2021-02-22 13:26:45
    赞同 展开评论 打赏
问答分类:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载

相关实验场景

更多