确认

  • [X] 我的版本是最新版本, 我的版本号与 version 相同, 并且项目里无依赖冲突
  • [X] 我已经在 issue 中搜索过, 确认问题没有被提出过
  • [X] 我已经修改标题, 将标题中的 描述 替换为遇到的问题

功能改进

希望达到 insert into t_user values(), (), (); 这种效果; 使用官方提供的方法注入插件 insertIntoSomeColumn 会出现源码中注释提到的数据库默认值的问题,所以基于此我这边 利用注入插件以及拦截器两个地方来实现真正的批量插入。原理就是通过具体的values反推出所需要的列。自定义的MysqlInsertBatch 里面只做 insertBatch 方法的MappedStatement对象添加 ,真正的批量sql生成由后边自定义的MysqlInsertBatchInterceptor来完成,部分源码片断 源码片断

此种批量添加要求:必须保证每个value里面的参数个数与类型完全一样

不知是否可采纳

参考资料

No response

Comment From: chess3cake

我是通过重载mapper/service方法解决的。Myabtisplus的BatchMethod用的是BatchStatement,但是切换BatchStatement/SimpleStatement存在可见性的问题,所以我都统一改成用SimpleStatement了。

Comment From: fengyujun

我这个是通过SqlInjector来实现的,定义一个新的批量插入方法,然后通过上面的流程来实现这个方法的内部逻辑。你这个具体是怎么实现的呢

Comment From: chess3cake

我这个是通过SqlInjector来实现的,定义一个新的批量插入方法,然后通过上面的流程来实现这个方法的内部逻辑。你这个具体是怎么实现的呢

我也是通过SqlInjector实现的,我是直接用Method生成了一个动态sql。重载DefaultSqlInjector,可以注册自定义的mapper method。

Comment From: fengyujun

我这个是通过SqlInjector来实现的,定义一个新的批量插入方法,然后通过上面的流程来实现这个方法的内部逻辑。你这个具体是怎么实现的呢

我也是通过SqlInjector实现的,我是直接用Method生成了一个动态sql。重载DefaultSqlInjector,可以注册自定义的mapper method。

但是你这个时候能确定具体有哪些列吗

Comment From: chess3cake

我这个是通过SqlInjector来实现的,定义一个新的批量插入方法,然后通过上面的流程来实现这个方法的内部逻辑。你这个具体是怎么实现的呢

我也是通过SqlInjector实现的,我是直接用Method生成了一个动态sql。重载DefaultSqlInjector,可以注册自定义的mapper method。

但是你这个时候能确定具体有哪些列吗

你的意思是,同一张表的批量插入,每次用的列不一样吗?

Comment From: fengyujun

我这个是通过SqlInjector来实现的,定义一个新的批量插入方法,然后通过上面的流程来实现这个方法的内部逻辑。你这个具体是怎么实现的呢

我也是通过SqlInjector实现的,我是直接用Method生成了一个动态sql。重载DefaultSqlInjector,可以注册自定义的mapper method。

但是你这个时候能确定具体有哪些列吗

你的意思是,同一张表的批量插入,每次用的列不一样吗?

对,根据用户给哪些属性赋值了,则将哪些属性转换为对应的sql列,而不能直接将对应的实体所有属性转换为列

Comment From: chess3cake

我这个是通过SqlInjector来实现的,定义一个新的批量插入方法,然后通过上面的流程来实现这个方法的内部逻辑。你这个具体是怎么实现的呢

我也是通过SqlInjector实现的,我是直接用Method生成了一个动态sql。重载DefaultSqlInjector,可以注册自定义的mapper method。

但是你这个时候能确定具体有哪些列吗

你的意思是,同一张表的批量插入,每次用的列不一样吗?

对,根据用户给哪些属性赋值了,则将哪些属性转换为对应的sql列,而不能直接将对应的实体所有属性转换为列

在我的mapper里有这么个基础方法,SqlMethod.DYNAMIC_INSERT_BATCH通过injector生成,在该方法中对不同null值的插入进行分组,再批量插入 ` default int insertBatch(@Param(Constants.COLL) Collection entities, int batchSize) { if (CollectionUtils.isEmpty(entities)) { return 0; } List fieldsList = null;

    MutableListMultimap<MultiObject, T> bulkEntities = Multimaps.mutable.list.empty();

    for (T entity : entities) {
        if (entity == null) {
            continue;
        }

        MultiObject nullOrEmptyFields = new MultiObject();

        try {
            if (fieldsList == null) {
                fieldsList = FieldUtils.getAllFieldsList(entity.getClass());
            }

            for (Field field : fieldsList) {
                String fieldName = field.getName();
                Object fieldValue = FieldUtils.readField(field, entity);
                if (fieldValue == null) {
                    nullOrEmptyFields.addObj(fieldName);
                } else if (fieldValue instanceof String str && str.isEmpty()) {
                    nullOrEmptyFields.addObj(fieldName);
                } else if (fieldValue instanceof Collection<?> coll && coll.isEmpty()) {
                    nullOrEmptyFields.addObj(fieldName);

                } else if (fieldValue instanceof Map<?, ?> map && map.isEmpty()) {
                    nullOrEmptyFields.addObj(fieldName);
                }
            }

        } catch (Exception e) {
            throw new EyTaxException("-1", "Failed to get field", e);
        }

        bulkEntities.put(nullOrEmptyFields, entity);

    }


    MybatisMapperProxy<?> mybatisMapperProxy = MybatisUtils.getMybatisMapperProxy(this);
    Class<?> mapperInterface = mybatisMapperProxy.getMapperInterface();
    SqlSession sqlSession = mybatisMapperProxy.getSqlSession();
    int res = 0;

    for (MultiObject bulk : bulkEntities.keySet()) {
        for (List<T> partition : ListUtils.partition(bulkEntities.get(bulk), batchSize)) {
            Map<String, Object> params = new HashMap<>();
            params.put(Constants.COLL, partition);
            params.put(Constants.MP_FILL_ET, partition.get(0));
            res += sqlSession.insert(mapperInterface.getName() + StringPool.DOT + SqlMethod.DYNAMIC_INSERT_BATCH.getMethod(), params);
        }
    }

    return res;


}

`