springcloud(springboot)框架下,mybatis实现大数据量插入

#为什么强调springcloud(springboot)框架?因为本文中,并没有对mybatis做配置改变。即使用了springboot零配置的特性。

在实际开发中,经常遇到大数据量的插入,比如导入excel,每行数据转换都是一条model,很容易出现几千上万条数据的导入。

解决大数据量插入且快速响应,有以下两种方式:

1、(文件解析成功后)将大数据量的插入任务扔给后台,告诉前端已经操作成功,稍后刷新页面。。

方法1:通过MQ扔给schedule定时器去执行插入任务

方法2:开启另一个Thread执行插入任务

2、想办法提升插入效率。

 

本文说明的是第二种方式,提升插入效率的办法。

springcloud(springboot)+mybatis框架下,代码结构是:mapper(java/xml)-->service(interface/impl)-->biz(interface/impl)

1、修改jdbcUrl,增加参数rewriteBatchedStatements=true使之能满足批量插入:

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://${db.host}:${db.port}/${db.schema}?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
spring.datasource.username=${db.username}
spring.datasource.password=${db.password}

2、在bizImpl内完成了数据组装(从excel或其他文档中读取数据,组装成List),调用service接口方法batchInsertByExecutor实现数据插入。

3、service接口类创建一个批量插入的接口方法:

boolean batchInsertByExecutor(List list);

4、serviceImpl实现service的批量插入接口方法:

(1)下方代码中,T是泛指某实体类,具体业务需要替换成具体的实体类。

(2)此方法中的内容都有注释,说明的比较清楚。比如为什么批量插入的方法,调用的是Mapper的单条插入方法,注释都有解释。

(3)此方法是在service层创建了一个批量插入的方法,没有改变Mapper和biz,也没有改变其他方法的数据插入方式和调用方式,因此不用担心其他的数据插入方法受影响。

(4)此方法利用ExecutorType.BATCH提交数据,满足数据回滚。即在bizImpl中调用此方法后,再抛出异常,此方法内插入的数据将回滚。

    /**
     ** 注入SqlSessionFactory,通过它创建session
     */
    @Autowired
    private SqlSessionFactory factory;

    @Override
    public boolean batchInsertByExecutor(List list) {
        // 1、设置ExecutorType.BATCH批量模式:
        // (1.1)把SQL语句发给数据库,数据库预编译好,数据库等待需要运行的参数,接收到参数后一次运行;
        // (1.2)ExecutorType.BATCH只打印一次SQL语句,多次设置参数步骤,
        // 2、设置autoCommit=false,改为手动提交事务
        SqlSession sqlSession = factory.openSession(ExecutorType.BATCH, false);

        try {

            // 每次手动提交事务时,批次已插入数据量。如1000条一次提交。
            int batchSize = 1000;
            int size = list.size();
            TMapper tMapper = sqlSession.getMapper(TMapper.class);
            for (int i = 0; i < size; i++) {

                // 调用单条插入,而非batchInsert。
                // 原因:ExecutorType.BATCH+insert并非直接插入,而是数据库预编译,等待事务提交
                T model = list.get(i);
                tMapper.insert(model);

                // 批次提交事务
                if (i > 0 && i % batchSize == 0) {
                    // 预插入,代替commit()和closeCache()
                    sqlSession.flushStatements();
                }
            }

            return true;
        } catch (Exception e) {
            e.printStackTrace();
            sqlSession.rollback();
        } finally {

            // 关闭事务
            sqlSession.close();
        }

        return false;
    }

以上就是批量插入的方法。基于springcloud(springboot)+mybatis(也可以是mybaits-plus),不改变mapper、biz(restful业务接口层),只在service创建一个独立的插入方法即可。

测试结果:

本人在实际项目中使用BATCH方法数据插入,包含文档解析等业务处理过程:

(1)4K+条数据插入,前端调用响应约1秒;

(2)1W+条数据插入,前端调用响应约2秒。

 

你可能感兴趣的:(spring-cloud,Mybatis,事务管理,springboot,mybatis,mysql)