mybatis-plus 扩展批量新增的实现

 更新时间:2023年01月09日 14:40:58   作者:JOEY P  
本文主要介绍了mybatis-plus 扩展批量新增的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言

最近发现公司的微服务项目中没有统一的批量新增方法,公司用的是MP插件,遇到批量新增都是单独去去编写xml实现,费时费力,而MP自带的批插方法只是实现了分批条sql,跟真正意义上一条sql实现批插还是有很大的性能差异,所以决定实现一个统一的批插方法。

一、MP如何扩展批量新增方法?

MP给我们预留了一个可以真正实现批插的插件InsertBatchSomeColumn,但是只是针对mysql数据库的,我们可以参照它稍加改造扩展一个针对oracle或者其他数据库的批插插件类,然后通过sql注入器的方式注入并初始化,就可以实现真正的批插了。

二、实现步骤

1.扩展批插类

代码如下(示例):

public class InsertBatchSomeColumnOracle extends AbstractMethod {

    /**
     * 字段筛选条件
     */
    @Setter
    @Accessors(chain = true)
    private Predicate<TableFieldInfo> predicate;

    @SuppressWarnings("Duplicates")
    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        KeyGenerator keyGenerator = new NoKeyGenerator();
        SqlMethod sqlMethod = SqlMethod.INSERT_ALL;
        List<TableFieldInfo> fieldList = tableInfo.getFieldList();
        String insertSqlColumn = tableInfo.getKeyInsertSqlColumn(false) +
                this.filterTableFieldInfo(fieldList, predicate, TableFieldInfo::getInsertSqlColumn, EMPTY);
        String tableName = tableInfo.getTableName();
        String columnScript = LEFT_BRACKET + insertSqlColumn.substring(0, insertSqlColumn.length() - 1) + RIGHT_BRACKET;
        String insertSqlProperty = tableInfo.getKeyInsertSqlProperty(ENTITY_DOT, false) +
                this.filterTableFieldInfo(fieldList, predicate, i -> i.getInsertSqlProperty(ENTITY_DOT), EMPTY);
        insertSqlProperty = " into " + tableName + columnScript + " values " + LEFT_BRACKET + insertSqlProperty.substring(0, insertSqlProperty.length() - 1) + RIGHT_BRACKET;
        String batchScript = SqlScriptUtils.convertForeach(insertSqlProperty, "list", null, ENTITY, EMPTY);
        String keyProperty = null;
        String keyColumn = null;
        // 表包含主键处理逻辑,如果不包含主键当普通字段处理
        if (tableInfo.havePK()) {
            if (tableInfo.getIdType() == IdType.AUTO) {
                /* 自增主键 */
                keyGenerator = new Jdbc3KeyGenerator();
                keyProperty = tableInfo.getKeyProperty();
                keyColumn = tableInfo.getKeyColumn();
            } else {
                if (null != tableInfo.getKeySequence()) {
                    keyGenerator = TableInfoHelper.genKeyGenerator(getMethod(), tableInfo, builderAssistant);
                    keyProperty = tableInfo.getKeyProperty();
                    keyColumn = tableInfo.getKeyColumn();
                }
            }
        }
        String sql = String.format(sqlMethod.getSql(), batchScript);
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
        return this.addInsertMappedStatement(mapperClass, modelClass, getMethod(), sqlSource, keyGenerator, keyProperty, keyColumn);
    }

    public String getMethod() {
        // 自定义 mapper 方法名
        return "insertBatchSomeColumnOracle";
    }
}

2.编写sql注入器

代码如下(示例):

public class MpSqlInjector extends DefaultSqlInjector {

    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
        // 防止父类的方法不可使用
        List<AbstractMethod> methodList = super.getMethodList(mapperClass);
        // 添加批量插入的方法
        methodList.add(new InsertBatchSomeColumn());
        methodList.add(new InsertBatchSomeColumnOracle());
        return methodList;
    }
}

3.spring容器中实例化sql注入器

代码如下(示例):

@Bean
public MpSqlInjector mpSqlInjector() {
    return new MpSqlInjector();
}

4.业务代码实现

代码如下(示例):

public interface MyBaseMapper<T> extends BaseMapper<T> {

    /**
     * 批量插入 (mysql)
     * @param entityList 实体列表
     * @return 影响行数
     */
    int insertBatchSomeColumn(Collection<T> entityList);

    /**
     * 批量插入 (oracle)
     * @param entityList 实体列表
     * @return 影响行数
     */
    int insertBatchSomeColumnOracle(Collection<T> entityList);
}


/**
     * 批量插入记录(选择字段,策略插入)
     *
     * @param entityList 实体对象集合
     */
    public void saveBatch(Collection<T> entityList) {
        if (DEFAULT_MUST_SAVE_BATCH) {
            ServiceAssert.isTrue(CollectionUtil.isNotEmpty(entityList), "批量插入传入空集合, 插入失败");
        }
        if (CollectionUtil.isEmpty(entityList)) {
            return;
        }
        int res;
        if (DATABASE_TYPE_ORACLE.equalsIgnoreCase(dbType)) {
            res = getBaseMapper().insertBatchSomeColumnOracle(entityList);
        } else {
            res = getBaseMapper().insertBatchSomeColumn(entityList);
        }
        ServiceAssert.isTrue(res == entityList.size(), "插入失败,请联系管理员");
    }
    /**
     * 批量插入记录(选择字段,策略插入)
     *
     * @param entityList 实体对象集合
     * @param batchSize 每批次插入数
     */
    public void saveBatch(Collection<T> entityList, int batchSize) {
        if (DEFAULT_MUST_SAVE_BATCH) {
            ServiceAssert.isTrue(CollectionUtil.isNotEmpty(entityList), "批量插入传入空集合, 插入失败");
        }
        if (CollectionUtil.isEmpty(entityList)) {
            return;
        }
        int size = entityList.size();
        int idxLimit = Math.min(batchSize, size);
        int i = 1;
        //保存单批提交的数据集合
        List<T> batchList = new ArrayList<>();
        for(Iterator<T> it = entityList.iterator(); it.hasNext(); ++i) {
            T element = it.next();
            batchList.add(element);
            int res;
            if (i == idxLimit) {
                if (DATABASE_TYPE_ORACLE.equalsIgnoreCase(dbType)) {
                    res = getBaseMapper().insertBatchSomeColumnOracle(batchList);
                } else {
                    res = getBaseMapper().insertBatchSomeColumn(batchList);
                }
                //每次提交后需要清空集合数据
                batchList.clear();
                idxLimit = Math.min(idxLimit + batchSize, size);
                ServiceAssert.isTrue(res == entityList.size(), "插入失败,请联系管理员");
            }
        }
    }

总结

遇到问题可以看看源码,说不定作者已经给你留好路了。

到此这篇关于mybatis-plus 扩展批量新增的实现的文章就介绍到这了,更多相关mybatis-plus 批量新增内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解Java实现多线程的三种方式

    详解Java实现多线程的三种方式

    线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。本文总结了Java多线程是三种实现方式,需要的可以参考一下
    2022-03-03
  • java swing实现电影购票系统

    java swing实现电影购票系统

    这篇文章主要为大家详细介绍了java swing实现电影购票系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-01-01
  • Java网络编程之IO模型阻塞与非阻塞简要分析

    Java网络编程之IO模型阻塞与非阻塞简要分析

    这篇文章主要介绍Java网络编程中的IO模型阻塞与非阻塞简要分析,文中附有示例代码,有需要的朋友可以借鉴参考下,希望能够有所帮助
    2021-09-09
  • 实例讲解String Date Calendar之间的转换

    实例讲解String Date Calendar之间的转换

    下面小编就为大家带来一篇实例讲解String Date Calendar之间的转换。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07
  • 浅谈Spring Boot日志框架实践

    浅谈Spring Boot日志框架实践

    这篇文章主要介绍了浅谈Spring Boot日志框架实践,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-03-03
  • PrintStream和PrintWriter的区别简介

    PrintStream和PrintWriter的区别简介

    这篇文章主要介绍了PrintStream和PrintWriter的区别简介,具有一定借鉴价值,需要的朋友可以参考下
    2018-01-01
  • 如何使用JFrame完成动态模拟时钟

    如何使用JFrame完成动态模拟时钟

    本文介绍了如何使用JFrame完成动态模拟时钟,需要的朋友可以参考下
    2015-08-08
  • Java中的线程死锁解读

    Java中的线程死锁解读

    这篇文章主要介绍了Java中的线程死锁解读,死锁就是指两个或两个以上的线程在抢占资源时,造成相互等待的现象,称为死锁,在没有外力的情况下是会一直等待无法执行下去,需要的朋友可以参考下
    2024-01-01
  • 在java中实现C#语法里的按引用传递参数的方法

    在java中实现C#语法里的按引用传递参数的方法

    下面小编就为大家带来一篇在java中实现C#语法里的按引用传递参数的方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-09-09
  • java数据结构与算法之插入算法实现数值排序示例

    java数据结构与算法之插入算法实现数值排序示例

    这篇文章主要介绍了java数据结构与算法之插入算法实现数值排序的方法,结合简单实例形式分析了插入算法的节点操作与排序相关实现技巧,需要的朋友可以参考下
    2016-08-08

最新评论