• mybatis-plus 根据任意字段saveOrUpdateBatch


    使用场景

    mybatisplus Iservice接口下的saveOrUpdateBatch方法默认是根据主键来决定是要更新还是插入的,如果要根据其他字段(必须是唯一约束,唯一约束字段可以是多个)更新的话,则需要在项目的service层重写该方法。

    方法源码

    @Transactional(
            rollbackFor = {Exception.class}
        )
        public boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize) {
            TableInfo tableInfo = TableInfoHelper.getTableInfo(this.entityClass);
            Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!", new Object[0]);
            String keyProperty = tableInfo.getKeyProperty();
            Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!", new Object[0]);
            return SqlHelper.saveOrUpdateBatch(this.entityClass, this.mapperClass, this.log, entityList, batchSize, (sqlSession, entity) -> {
                Object idVal = ReflectionKit.getFieldValue(entity, keyProperty);
                return StringUtils.checkValNull(idVal) || CollectionUtils.isEmpty(sqlSession.selectList(this.getSqlStatement(SqlMethod.SELECT_BY_ID), entity));
            }, (sqlSession, entity) -> {
                MapperMethod.ParamMap<T> param = new MapperMethod.ParamMap();
                param.put("et", entity);
                sqlSession.update(this.getSqlStatement(SqlMethod.UPDATE_BY_ID), param);
            });
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    从源码中可以看出实现saveOrUpdateBatch的主要方法就是SqlHelper.saveOrUpdateBatch

    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) -> {
                if (predicate.test(sqlSession, entity)) {
                    sqlSession.insert(sqlStatement, entity);
                } else {
                    consumer.accept(sqlSession, entity);
                }
    
            });
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    该方法的最后两个参数predicate,consumer
    predicate 这个函数是用于判断是否要进行插入操作 true插入,false:则通过consumer 函数执行更新

    方法改造

    注意:写在项目操作对应表的service层
    首先在service层定义接口

    boolean saveOrUpdateBatchByAgentIdAndPeriodAndType(List<Entity> list);
    
    • 1

    类为数据库表对应的实体类,agentId,period,type,这个三个字段为表的唯一约束,即当表中存在这三个字段组合对应的记录时则进行更新操作,不存在则进行插入操作
    service层接口实现

    @Transactional(rollbackFor = Exception.class)
        @DS("XXXX")//如果为多数据源,这里要指明具体操作的数据源名称
        public boolean saveOrUpdateBatchByAgentIdAndPeriodAndType(List<Entity> list) {
    
            return SqlHelper.saveOrUpdateBatch(entityClass, this.mapperClass, super.log, list, DEFAULT_BATCH_SIZE, (sqlSession, entity) -> {//这里主要是查询唯一约束对应的记录是否存在
                LambdaQueryWrapper<Entity> queryWrapper = Wrappers.<Entity>lambdaQuery()
                        .eq(Entity::getAgentId, entity.getAgentId()).eq(Entity::getPeriod,entity.getPeriod())
                        .eq(Entity::getType,entity.getType());
                Map<String, Object> map = CollectionUtils.newHashMapWithExpectedSize(1);
                map.put(Constants.WRAPPER, queryWrapper);
                return CollectionUtils.isEmpty(sqlSession.selectList(getSqlStatement(SqlMethod.SELECT_LIST), map));
            }, (sqlSession, entity) -> {
                LambdaUpdateWrapper<Entity> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
                lambdaUpdateWrapper.eq(Entity::getAgentId, entity.getAgentId()).eq(Entity::getPeriod,entity.getPeriod())
                        .eq(Entity::getType,entity.getType());
                Map<String, Object> param = CollectionUtils.newHashMapWithExpectedSize(2);
                param.put(Constants.ENTITY, entity);
                param.put(Constants.WRAPPER, lambdaUpdateWrapper);
                sqlSession.update(getSqlStatement(SqlMethod.UPDATE), param);
            });
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    非批量的saveOrUpdate也可以按照这种方式进行改造

  • 相关阅读:
    Leetcode 416、分割等和子集
    做推特群发群推“三不要怕”
    fabric.js的使用
    如何让Android平台像IPC一样实现GB28181前端设备接入
    AI 就是要取代薪酬高的岗位,程序员们怎么办?
    vue3中的pinia
    yaml&easydict作为参数文件
    快讯:飞书玩家大会线上举行;微信支付推出“教培服务工具箱”
    systemverilog学习 ---随机化(2)
    CentOS7安装MySQL8
  • 原文地址:https://blog.csdn.net/chengmeng_123/article/details/134462151