MyBatis的批量更新或插入的正确姿势

2021-08-27 17:03:28 浏览数 (1)

之前写过一篇mybatis批量插入的文章:https://cloud.tencent.com/developer/article/1868919

这次补充:

根据https://blog.csdn.net/huanghanqian/article/details/83177178所述千条以上的批量插入或者更新慎用foreach方式,ExecutorType.BATCH 的插入方式,性能显著提升

那么怎么使用这种方式?

可以参考我上面的那篇文章。

另外发现篇不错的介绍此内容的英文文章:http://pretius.com/how-to-use-mybatis-effectively-perform-batch-db-operations/

此处简单翻译如下:

MyBatis的批处理配置

代码语言:javascript复制
@Bean
    @Primary
    public SqlSessionTemplate sqlSessionTemplate() throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory());
    }

    @Bean(name=MyBatisProperties.BATCH_SQL_SESSION_TEMPLATE)
    public SqlSessionTemplate batchSqlSessionTemplate() throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory(), ExecutorType.BATCH);
    }

可以使用上面两种session模板俩处理不同的模型:

1、标准- 标准的或单条操作

2、批量- 批量或者成块的处理

注意:一个session模板只能有一种处理模型

默认的mybatis mapper使用默认的标准的session模板,而不用批处理的session模板。

如果我们想要一个mapper使用批处理session,我们需要将其从其他mapper中分离。

BatchConfiguration配置类中的代码:

代码语言:javascript复制
    public final static String BATCH_FORECAST_MAPPER = "batchForecastMapper";

    @Autowired
    @Qualifier(MyBatisProperties.BATCH_SQL_SESSION_TEMPLATE)
    private SqlSessionTemplate batchSqlSessionTemplate;

    @Bean
    public MapperFactoryBean batchForecastMapper() {
        MapperFactoryBean mapper = new MapperFactoryBean();
        mapper.setMapperInterface(ForecastMapper.class);
        mapper.setSqlSessionTemplate(batchSqlSessionTemplate);
        return mapper;
    }

简单的mapper类,要加上bean的名称为BatchConfiguration.BATCH_FORECAST_MAPPER

代码语言:javascript复制
    public interface ForecastMapper {
        void createForecast(@Param("forecast") Forecast forecast, @Param("audit") AuditData audit);

        void updateForecast(@Param("forecast") Forecast forecast, @Param("deleted") boolean deleted, @Param("audit") AuditData audit);

        @Flush
        List flush();
    }

添加了flush方法,是为了控制批量插入的大小。返回值是影响的行数。

service中的用法

代码语言:javascript复制
    @Autowired
    @Qualifier(BatchConfiguration.BATCH_FORECAST_MAPPER)
    private ForecastMapper batchForecastMapper;

    ...
    if (!toUpdate.isEmpty()) {
        for (ForecastUpdate forecast : toUpdate) {
            batchForecastMapper.updateForecast(forecast, forecast.isDeleted(), auditData);
        }
        batchForecastMapper.flush();
    }
    for (ForecastUpdate forecast : toCreate) {
        batchForecastMapper.createForecast(forecast, auditData);
        // Oracle does not support useGeneratedKeys in batch update, but flush after each statement works.
        batchForecastMapper.flush();
    }

调用flush时会调用doFlushStatement方法把数据批量刷新到表中。另外flush方法在每个事务结束前或者select语句调用前会自动触发。

潜在的问题:

Oracle 数据库中需要每个插入语句后都要调用flush方法,来使得useGeneratedKeys生效。

参考文章:  Mybatis Executor原理分析

0 人点赞