springboot 集成的 mybatis 设置 executorType 为 batch模式

三种执行器

mybatis提供三种sql执行器,分别是SIMPLE(默认)、REUSE、BATCH。

  • SIMPLE(SimpleExecutor),相当于JDBC的stmt.execute(sql) 执行完毕即关闭即 stmt.close()

  • REUSE(ReuseExecutor),相当于JDBC的stmt.execute(sql) 执行完不关闭,而是将stmt存入 Map<String, Statement>中缓存,其中key为执行的sql模板;

  • BATCH(BatchExecutor),相当于JDBC语句的 stmt.addBatch(sql),即仅将执行SQL加入到批量计划但是不真正执行, 所以此时不会执行返回受影响的行数,而只有执行stmt.execteBatch()后才会真正执行sql

三种方式各有利弊

方式优势劣势
SIMPLE默认执行器, 节约服务器资源每次都要开关Statement
REUSE提升后端接口处理效率每次一个新sql都缓存,增大JVM内存压力
BATCH专门用于更新插入操作,效率最快对select 不适用,另外特殊要求,比如限制一次execteBatch的数量时需要写过滤器定制

设置为batch模式

springboot 下开启 batch模式比较简单,

全局方式开通batch

在yml文件中添加 如下配置即可。

mybatis:
  executor-type: batch

原因是mybatis-spring-boot源码,this.properties 就是读取了yml中的内容:

@Bean
    @ConditionalOnMissingBean
    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        ExecutorType executorType = this.properties.getExecutorType();
        if (executorType != null) {
            return new SqlSessionTemplate(sqlSessionFactory, executorType);
        } else {
            return new SqlSessionTemplate(sqlSessionFactory);
        }
    }

方法中直接指定batch

这个方式的缺陷就是事务方面不受spring管理了。

    @Autowired
    protected SqlSessionFactory sqlSessionFactory;
    
    public void saveOrder(Order t) {
		SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
		OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
		
		try{
			orderMapper.save(t);
			sqlSession.commit();
		}catch(Exception e){
			logger.error("批量导入数据异常,事务回滚", e);
			sqlSession.rollback();
		}finally {
			if (sqlSession != null) {
		  		sqlSession.close();
			}
	}
}

后记

如果单纯的数据同步,其实可以建议 原生JDBC !,当然可以采用封装的JDBC工具类,真心快的一笔!

    // 从spring管理的数据源中直接拿
    @Resource(name = "dataSource")
    private DataSource dataSource;
    
    @Test
    public void jdbcTest() throws SQLException {
        Connection connection = dataSource.getConnection();
        connection.setAutoCommit(false);
        String sql = "INSERT INTO tpm_user (id,name,createDate,remark) VALUES(?,?,?,?) ";

        PreparedStatement statement = connection.prepareStatement(sql);
        for (int i = 0; i < 1000000; i++) {
            statement.setLong(1, snowflakeService.nextId());
            statement.setString(2, "name" + i);
            statement.setDate(3, new Date(System.currentTimeMillis()));
            statement.setString(4, "remark" + i);
            statement.addBatch();
        }
        long start = System.currentTimeMillis();
        statement.executeBatch();
        connection.commit();
        
        statement.close();
        connection.close();
        System.out.print("耗时:");
        System.out.println(System.currentTimeMillis() - start);
    }

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐