怎样提高mybatis-plus中saveBatch方法的效率

 更新时间:2023年07月14日 10:57:38   作者:草履虫稽亚娜  
这篇文章主要介绍了怎样提高mybatis-plus中saveBatch方法的效率问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

提高mybatis-plus中saveBatch方法的效率

MyBatis-Plus中的saveBatch方法是一个很方便的批量插入数据的方法,但是如果插入的数据量很大时,可能会出现效率较低的情况。

提高saveBatch方法效率的方法

1.批量插入的数据量不宜过大,否则可能会导致内存溢出。建议根据实际情况选择合适的批量插入数据的数量。

2.如果插入的数据是从文件或其他数据源中读取的,可以使用流式插入的方式,将数据流分批插入数据库,可以减小内存压力。

3.在执行saveBatch方法前,可以通过开启MyBatis-Plus的批量插入功能,将多条SQL语句合并成一条执行,减少与数据库的交互次数。可以通过以下代码开启批

mybatis-plus saveOrUpdateBatch踩坑

mybatis-plus版本: 3.5.1

调用方法

@Transactional(rollbackFor = Exception.class)  
default boolean saveOrUpdateBatch(Collection<T> entityList) {  
    return saveOrUpdateBatch(entityList, DEFAULT_BATCH_SIZE);  
}

问题说明

当对entityList进行批量更新操作时,方法内部会根据主键查询该记录,导致批量更新操作十分缓慢,具体代码如下

@Transactional(rollbackFor = Exception.class)
@Override
public boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize) {
    TableInfo tableInfo = TableInfoHelper.getTableInfo(entityClass);
    Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!");
    String keyProperty = tableInfo.getKeyProperty();
    Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!");
    return SqlHelper.saveOrUpdateBatch(this.entityClass, this.mapperClass, this.log, entityList, batchSize, (sqlSession, entity) -> {
        Object idVal = tableInfo.getPropertyValue(entity, keyProperty);
        // 当主键存在时,会执行sqlSession.selectList(getSqlStatement(SqlMethod.SELECT_BY_ID), entity)查询该条记录
        return StringUtils.checkValNull(idVal) || CollectionUtils.isEmpty(sqlSession.selectList(getSqlStatement(SqlMethod.SELECT_BY_ID), entity));
    }, (sqlSession, entity) -> {
        MapperMethod.ParamMap<T> param = new MapperMethod.ParamMap<>();
        param.put(Constants.ENTITY, entity);
        sqlSession.update(getSqlStatement(SqlMethod.UPDATE_BY_ID), param);
    });
}
public static <E> boolean saveOrUpdateBatch(Class<?> entityClass, Class<?> mapper, Log log, Collection<E> list, int batchSize, BiPredicate<SqlSession, E> predicate, BiConsumer<SqlSession, E> consumer) {
    String sqlStatement = getSqlStatement(mapper, SqlMethod.INSERT_ONE);
    return executeBatch(entityClass, log, list, batchSize, (sqlSession, entity) -> {
        // 执行predicate
        if (predicate.test(sqlSession, entity)) {
            sqlSession.insert(sqlStatement, entity);
        } else {
            consumer.accept(sqlSession, entity);
        }
    });
}
public static <E> boolean executeBatch(Class<?> entityClass, Log log, Collection<E> list, int batchSize, BiConsumer<SqlSession, E> consumer) {
    Assert.isFalse(batchSize < 1, "batchSize must not be less than one");
    return !CollectionUtils.isEmpty(list) && executeBatch(entityClass, log, sqlSession -> {
        int size = list.size();
        int idxLimit = Math.min(batchSize, size);
        int i = 1;
        for (E element : list) {
            // 循环每条记录,执行consumer,在此次调用中,consumer中会执行predicate,当该条记录主键不为空时,会通过主键查询该记录
            consumer.accept(sqlSession, element);
            if (i == idxLimit) {
                sqlSession.flushStatements();
                idxLimit = Math.min(idxLimit + batchSize, size);
            }
            i++;
        }
    });
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • MyBatis 使用权威指南

    MyBatis 使用权威指南

    MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集,本文给大家介绍MyBatis 使用指南,一起看看吧
    2017-03-03
  • Java中创建对象的5种方式总结

    Java中创建对象的5种方式总结

    本篇文章主要介绍了Java中创建对象的5种方式总结,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-02-02
  • SpringBoot自动装配原理详细解析

    SpringBoot自动装配原理详细解析

    这篇文章主要介绍了SpringBoot自动装配原理详细解析,一个对象交给Spring来管理的三种方式 @Bean @Compoment @Import,
    @Bean主要在@Configuration中,通过方法进行注入相关的Bean,@Compoent与@Service归为一类,在类上加注入对应的类,需要的朋友可以参考下
    2024-01-01
  • SpringBoot 二维码生成base64并上传OSS的实现示例

    SpringBoot 二维码生成base64并上传OSS的实现示例

    本文主要介绍了SpringBoot 二维码生成base64并上传OSS的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-05-05
  • Java中Map.merge()方法使用示例详解

    Java中Map.merge()方法使用示例详解

    这篇文章主要介绍了Map.merge()方法使用和介绍,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-08-08
  • 浅谈异常结构图、编译期异常和运行期异常的区别

    浅谈异常结构图、编译期异常和运行期异常的区别

    下面小编就为大家带来一篇浅谈异常结构图、编译期异常和运行期异常的区别。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-09-09
  • Java SPI机制详细介绍

    Java SPI机制详细介绍

    大家好,本篇文章主要讲的是Java SPI机制详细介绍,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2021-12-12
  • Java 多个时间区间进行合并处理方法

    Java 多个时间区间进行合并处理方法

    用户在选择多个时间区间之后,如选择的时间区间连续或者有重叠,需要对所选的时间区间进行合并,这其实是一个区间合并问题,下面通过本文给大家介绍Java 多个时间区间进行合并处理的解决方案,一起看看吧
    2024-02-02
  • 如何在yml配置文件中使用中文注解

    如何在yml配置文件中使用中文注解

    这篇文章主要介绍了如何在yml配置文件中使用中文注解,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-10-10
  • SpringBoot中的@FeignClient注解使用

    SpringBoot中的@FeignClient注解使用

    文章主要介绍了SpringCloud中的@FeignClient注解的使用及其参数详解,包括value/name、url、path、configuration、fallback/fallbackFactory、contextId等,通过@FeignClient注解,可以方便地声明一个REST客户端,并定义与目标服务通信的接口
    2024-11-11

最新评论