Mybatis-plus批量操作

这篇具有很好参考价值的文章主要介绍了Mybatis-plus批量操作。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

        使用Mybatis-plus可以很方便的实现批量新增和批量修改,不仅比自己写foreach遍历方便很多,而且性能也更加优秀。但是Mybatis-plus官方提供的批量修改和批量新增都是根据id来修改的,有时候我们需求其他字段,所以就需要我们自己修改一下。

一、批量修改

        在Mybatis-plus的IService接口中有updateBatchById方法,我们常用以下方法根据id批量修改数据。

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

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updateBatchById(Collection<T> entityList, int batchSize) {
        String sqlStatement = getSqlStatement(SqlMethod.UPDATE_BY_ID);
        return executeBatch(entityList, batchSize, (sqlSession, entity) -> {
            MapperMethod.ParamMap<T> param = new MapperMethod.ParamMap<>();
            param.put(Constants.ENTITY, entity);
            sqlSession.update(sqlStatement, param);
        });
    }

但是当我们想根据其他字段批量修改数据时,该方法就无能为力了。所以我们就可以根据第二个updateBatchById方法在自己的service类里面写一个新的批量新增方法。

    public boolean updateBatchByColumn(Collection<?> entityList, String idCard) {
        String sqlStatement = getSqlStatement(SqlMethod.UPDATE);
        return executeBatch(entityList, (sqlSession, entity) -> {
            LambdaUpdateWrapper<SysUser> updateWrapper = Wrappers.<SysUser>lambdaUpdate()
                    .eq(SysUser::getIdCard, idCard);
            Map<String, Object> param = CollectionUtils.newHashMapWithExpectedSize(2);
            param.put(Constants.ENTITY, entity);
            param.put(Constants.WRAPPER, updateWrapper);
            sqlSession.update(sqlStatement, param);
        });
    }

注意sqlStatement是使用的SqlMethod.UPDATE,SysUser对象是举例,使用的是若依的用户数据。

二、批量新增或修改

        在Mybatis-plus的ServiceImpl 类中有一个saveOrUpdateBatch 方法用于批量新增或修改,通过CollectionUtils.isEmpty(sqlSession.selectList(getSqlStatement(SqlMethod.SELECT_BY_ID), entity))根据id查询数据是否已存在,不存在新增,存在则修改,源码如下:

    @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);
            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);
        });
    }

最终调用的是SqlHelper.saveOrUpdateBatch方法,该方法第六个参数是BiPredicate,这就是用于判断数据库中数据是否存在的关键,所以我们需要修改这个函数式接口,修改为根据其他条件查询数据库。该方法的第七个参数是BiConsumer,该函数式接口用于修改数据,如果不想根据id修改数据,可以参考第一部门进行修改。

    @Transactional(rollbackFor = Exception.class)
    public boolean saveOrUpdateBatchByColumn(Collection<?> entityList, String idCard) {

        return SqlHelper.saveOrUpdateBatch(this.entityClass, this.mapperClass, super.log, entityList, DEFAULT_BATCH_SIZE, (sqlSession, entity) -> {
            LambdaQueryWrapper<SysUser> queryWrapper = Wrappers.<SysUser>lambdaQuery()
                    .eq(SysUser::getIdCard, idCard);
            Map<String, Object> map = CollectionUtils.newHashMapWithExpectedSize(1);
            map.put(Constants.WRAPPER, queryWrapper);
            return CollectionUtils.isEmpty(sqlSession.selectList(getSqlStatement(SqlMethod.SELECT_LIST), map));
        }, (sqlSession, entity) -> {
            Map<String, Object> param = CollectionUtils.newHashMapWithExpectedSize(2);
            param.put(Constants.ENTITY, entity);
            sqlSession.update(getSqlStatement(SqlMethod.UPDATE_BY_ID), param);
        });
    }

三、不使用Mybatis-plus进行批量操作

        有时候项目里没有引用Mybatis-plus,但是也想进行批量操作,数据量大了后foreach循环会影响性能。所以可以参考Mybatis-plus的批量操作,编写在mybatis环境下的批量操作,代码如下:

@Component
public class MybatisBatchUtils {

    private static final int BATCH_SIZE = 1000;

    @Autowired
    private SqlSessionFactory sqlSessionFactory;

    public <T,U,R> boolean batchUpdateOrInsert(List<T> data, Class<U> mapperClass, BiFunction<T,U,R> function) {
        int i = 1;
        SqlSession batchSqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
        try {
            U mapper = batchSqlSession.getMapper(mapperClass);
            int size = data.size();
            for (T element : data) {
                function.apply(element, mapper);
                if ((i % BATCH_SIZE == 0) || i == size) {
                    batchSqlSession.flushStatements();
                }
                i++;
            }
            // 非事务环境下强制commit,事务情况下该commit相当于无效
            batchSqlSession.commit(!TransactionSynchronizationManager.isSynchronizationActive());
            return true;
        } catch (Exception e) {
            batchSqlSession.rollback();
            throw new RuntimeException(e);
        } finally {
            batchSqlSession.close();
        }
    }
}

写在最后的话

        Mybatis-plus真好用,少写好多代码。有些不太适用的方法,也可以很简单在官方的基础上进行扩展。文章来源地址https://www.toymoban.com/news/detail-678320.html

到了这里,关于Mybatis-plus批量操作的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Mybatis-plus的操作(新增,修改)

    一般同时会引入Druid。 MP会默认将模型类的类名首字母小写作为表名使用,假如数据库名称都以tbl_开头,那么我们就需要将所有的模型类上添加@TableName,配置起来还是比较繁琐,简化方式可以在配置文件中配置如下内容: 设置前缀的内容,这样MP就会拿tbl_加上模型类的首字

    2024年02月02日
    浏览(49)
  • Mybatis-Plus批量更新原理

    IService的updateBatchById方法 默认batchSize = 1000 com.baomidou.mybatisplus.extension.service.impl.ServiceImpl#updateBatchById 构建了一个回调,进入executeBatch方法 在这个方法基本就能看出来了,执行1000次方法后执行一次flushStatements,也就是说理论上是积累了1000个更新sql,才进行一次数据库更新 使用

    2024年02月05日
    浏览(50)
  • mybatis-plus 批量插入示例

    正常我们使用mybatis-plus插入的时候,首先想到的是  saveBatch 方法,不过看了下打印出来的sql和底层代码,才发现它并不是真正的批量插入。     实现层   ServiceImpl 中的代码为 通过监控控制台发现,它只是循环每1000条去插入,效率非常低。   参考网友的文章,找到一个支

    2024年02月15日
    浏览(38)
  • Mybatis-plus---的批量插入

    批量插入 一、继承IService(伪批量) 二、insertBatchSomeColumn Mybatis-plus很强,为我们诞生了极简CURD操作,但对于数据批量操作,显然默认提供的insert方法是不够看的了,于是它和它来了!!! Mybatis-plus提供的两种插入方式          继承IService(伪批量)         insertBatchSo

    2024年02月16日
    浏览(47)
  • mybatis-plus的批量新增insertBatchSomeColumn

    MyBatis-Plus 是基于 MyBatis 进行封装的一套优秀的持久层框架,它提供了丰富的便捷操作方法和强大的代码生成器,大大简化了 MyBatis 的使用。在 MyBatis-Plus 中,我们可以使用 insertBatchSomeColumn 方法来实现批量新增指定字段的操作。 mybatis-plus 的  IService 接口  默认提供   saveBat

    2024年02月01日
    浏览(39)
  • MyBatis-plus的批量插入方式对比分析

      【摘要】Mybatis批量插入一直是开发者重点关注的问题,本文列举了Mybatis的五种插入方式进行对比分析,验证了五种批量插入的方式的优先级。   略。 1、编写UserService服务类,测试一万条数据的耗时情况: 2、编写UserMapper接口 3、编写UserMapper.xml文件 4、进行单元测试

    2024年02月07日
    浏览(54)
  • 批量插入或更新数据(MyBatis-plus框架)

    目录 1.场景说明 2.DUPLICATE 和REPLACE比较 3.批量插入或者更新(两种方式) 方式一:mybatis-plus的saveOrUpdateBatch方法 问题:如果操作类集成了基础类,比如封装了BaseEntity去集成,那么这样使用会出问题 方式二:on duplicate key (推荐) 4.注意 5.常见问题  插入数据时,我们经常会遇到这

    2024年02月04日
    浏览(80)
  • mybatis-plus批量保存异常及效率优化

    最近基于自己公司内部服务维护,发现其中调度中心近期出现不少错误日志,但是该任务却是正常执行,生成的报表数据也是正常的,所以很多天没有发现问题 这就匪夷所思了,    经仔细排查发现,是触发了feign超时hystrix熔断器机制 也就是说子服务出现了执行时间过长的

    2024年01月16日
    浏览(33)
  • spring boot集成mybatis-plus——Mybatis Plus 批量 Insert_新增数据(图文讲解)

     更新时间 2023-01-10 16:02:58 大家好,我是小哈。 本小节中,我们将学习如何通过 Mybatis Plus 实现 MySQL 批量插入数据。 先抛出一个问题:假设老板给你下了个任务,向数据库中添加 100 万条数据,并且不能耗时太久! 通常来说,我们向 MySQL 中新增一条记录,SQL 语句类似如下:

    2024年02月04日
    浏览(46)
  • Mybatis-plus通过其他字段批量更新或新增

    根据某个或者多个非ID字段进行批量更新 示例通过名称与id两个字段更新 引用mybatis-plus根据某个指定字段批量更新数据库 通过其他字段批量更新或新增

    2024年02月12日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包