我的编程空间,编程开发者的网络收藏夹
学习永远不晚

MyBatis-plus批量插入的通用方法是什么

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

MyBatis-plus批量插入的通用方法是什么

这篇文章主要介绍“MyBatis-plus批量插入的通用方法是什么”,在日常操作中,相信很多人在MyBatis-plus批量插入的通用方法是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”MyBatis-plus批量插入的通用方法是什么”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

1. MyBatis-plus 的批量保存方法

MyBatis-plus 中默认提供了一个批量保存数据到数据库的方法,也就是 IService#saveBatch() 接口方法。这个方法的实现为 ServiceImpl#saveBatch(),其源码实际处理的关键如下,从中可以知道 IService#saveBatch() 并不是一个真正的批量插入数据的方法

  1. 调用 ServiceImpl#sqlStatement() 使用 SqlMethod.INSERT_ONE 枚举结合实体类确定一个全路径方法名称,这个名称将用于匹配实体对应的库表的单个插入方法的 MappedStatement 对象

  2. 调用 ServiceImpl#executeBatch() 方法遍历 Entity 的集合,使用单个插入的方法为每个实体组装一个 INSERT INTO 语句,遍历结束后 flush,一次性将所有生成的 INSERT INTO 语句推给数据库执行

举例来说,如果调用 IService#saveBatch() 方法保存有2个元素的实体集合 List<Node> 数据到数据库,其执行的 SQL 语句如下

存在 2 条:
INSERT INTO node (name, version) VALUES (&lsquo;nathan&rsquo;,1);
INSERT INTO node (name, version) VALUES (&lsquo;bob&rsquo;,1);

而如果是数据库批量插入,其执行的 SQL 语句应该如下

只有 1 条:
INSERT INTO node (name, version) VALUES (&lsquo;nathan&rsquo;,1), (&lsquo;bob&rsquo;,1);

    @Transactional(rollbackFor = Exception.class)    @Override    public boolean saveBatch(Collection<T> entityList, int batchSize) {        String sqlStatement = sqlStatement(SqlMethod.INSERT_ONE);        return executeBatch(entityList, batchSize, (sqlSession, entity) -> sqlSession.insert(sqlStatement, entity));    }        protected String sqlStatement(SqlMethod sqlMethod) {        return SqlHelper.table(entityClass).getSqlStatement(sqlMethod.getMethod());    }        protected <E> boolean executeBatch(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(sqlSession -> {            int size = list.size();            int i = 1;            for (E element : list) {                consumer.accept(sqlSession, element);                if ((i % batchSize == 0) || i == size) {                    sqlSession.flushStatements();                }                i++;            }        });    }

2. MyBatis-plus 的批量插入方法

2.1 通用批量插入方法 InsertBatchSomeColumn

事实上 MyBatis-plus 提供了真正的批量插入方法 InsertBatchSomeColumn,只不过这个方法只在 MySQL 数据库下测试过,所以没有将其作为默认通用方法添加到 SqlMethod 中

从其源码实现不难看出,InsertBatchSomeColumn 其实就是提供了一个使用 foreach 标签的 SQL 脚本,不了解这个标签的读者参考自定义批量插入大致理解即可

@NoArgsConstructor@AllArgsConstructorpublic class InsertBatchSomeColumn 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_ONE;        List<TableFieldInfo> fieldList = tableInfo.getFieldList();        String insertSqlColumn = tableInfo.getKeyInsertSqlColumn(false) +            this.filterTableFieldInfo(fieldList, predicate, TableFieldInfo::getInsertSqlColumn, EMPTY);        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 = LEFT_BRACKET + insertSqlProperty.substring(0, insertSqlProperty.length() - 1) + RIGHT_BRACKET;        String valuesScript = SqlScriptUtils.convertForeach(insertSqlProperty, "list", null, ENTITY, COMMA);        String keyProperty = null;        String keyColumn = null;        // 表包含主键处理逻辑,如果不包含主键当普通字段处理        if (StringUtils.isNotBlank(tableInfo.getKeyProperty())) {            if (tableInfo.getIdType() == IdType.AUTO) {                                keyGenerator = new Jdbc3KeyGenerator();                keyProperty = tableInfo.getKeyProperty();                keyColumn = tableInfo.getKeyColumn();            } else {                if (null != tableInfo.getKeySequence()) {                    keyGenerator = TableInfoHelper.genKeyGenerator(getMethod(sqlMethod), tableInfo, builderAssistant);                    keyProperty = tableInfo.getKeyProperty();                    keyColumn = tableInfo.getKeyColumn();                }            }        }        String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), columnScript, valuesScript);        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);        return this.addInsertMappedStatement(mapperClass, modelClass, getMethod(sqlMethod), sqlSource, keyGenerator, keyProperty, keyColumn);    }    @Override    public String getMethod(SqlMethod sqlMethod) {        // 自定义 mapper 方法名        return "insertBatchSomeColumn";    }}

2.2 InsertBatchSomeColumn 的使用

由于InsertBatchSomeColumn 是框架已经定义好的通用方法,所以使用者只要引入即可,简单来说只需要进行以下几个步骤:

  • 新增 SQL 注入器

  • 新增配置类将 SQL 注入器添加到容器

  • 新增基类 Mapper,注意这个基类中的批量插入方法名称要和 InsertBatchSomeColumn#getMethod() 方法返回的字符串一致,也就是 insertBatchSomeColumn

具体做法读者请参考 MyBatis-plus 自定义通用方法及其实现原理,本文不再赘述

 经过以上配置,最终具体的业务类 Mapper 只要继承新增的基类 Mapper 就具备了批量插入的功能,笔者习惯将 Mapper 封装在一个 RepositoryService 中对外提供能力,则各个业务类只需要实现类似如下的 NodeRepositoryServiceImpl#insertBatch() 方法即可以对外提供批量插入的功能

    @Override    public int insertBatch(List<Node> entityList) {        if (CollectionUtils.isEmpty(entityList)) {            return 0;        }        return getBaseMapper().insertBatchSomeColumn(entityList);    }

3. 批量插入 MySQL 数据库的坑

3.1 MySQL 对非 NULL 字段插入 NULL 值的处理

使用 MyBatis-plus 批量插入的方法插入 MySQL 记录时需要注意,调用批量插入的方法一定要保证确实是要插入多条数据,如果调用批量插入的方法只插入了单条数据,非常有可能遇到非 NULL 字段插入 NULL 值的错误:

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'xxx_name' cannot be null

这是因为我们借助 Entity 插入数据时经常会忽略一些表中有默认值的非 NULL 字段对应的属性的赋值,而从批量插入的 SQL 语句的执行角度来看,这样做也就是往非 NULL 字段插入了 NULL 值。实际上 MySQL 对于非 NULL 字段插入 NULL 值是有兼容处理的,感兴趣的读者可前往 官方传送门,本文摘录如下:

简单来说,对于插入 NULL 值到非 NULL 字段的情况分为两种处理方式:

  • 如果是批量插入多条数据,则会将 NULL 值转化为默认值插到非 NULL 字段(也就是本文批量插入方法插入多条数据的情形)

  • 如果是单条数据插入,则抛出异常,失败结束(对应本文批量插入方法只插入了单条数据的情形)

Inserting NULL into a column that has been declared NOT NULL. For multiple-row INSERT statements or INSERT INTO ... SELECT statements, the column is set to the implicit default value for the columndata type. This is 0 for numeric types, the empty string ('') for string types, and the “zero” valuefor date and time types. INSERT INTO ... SELECT statements are handled the same way as multiple-rowinserts because the server does not examine the result set from the SELECT to see whether it returnsa single row. (For a single-row INSERT, no warning occurs when NULL is inserted into a NOT NULL column.Instead, the statement fails with an error.)

3.2 解决方法

解决方法很简单,只要在批量插入的时候判断一下 Entity 集合的大小即可,如果集合中只有一条数据,则调用插入单条数据的方法

  • MyBatis-plus 单条数据插入之所以不会有往非 NULL 字段插入 NULL 值的问题,是因为其单条插入数据的 SQL 脚本能根据 Entity 的属性赋值情况动态调整,对于 Entity 中值为 NULL 的属性,默认不会将其对应的字段添加到执行的 SQL 语句中

举例来说,如 Node 含有两个属性,分别是 name 和 version,则对于属性值不同的情况最终执行的 SQL 语句也不一样

version 为 NULL
INSERT INTO node (name) VALUES (&lsquo;nathan&rsquo;);
2. version 不为 NULL
INSERT INTO node (name, version) VALUES (&lsquo;nathan&rsquo;,1);

    @Override    public int insertBatch(List<Node> entityList) {        if (CollectionUtils.isEmpty(entityList)) {            return 0;        }        if (1 == entityList.size()) {            return getBaseMapper().insert(entityList.get(0));        }        return getBaseMapper().insertBatchSomeColumn(entityList);    }

到此,关于“MyBatis-plus批量插入的通用方法是什么”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

MyBatis-plus批量插入的通用方法是什么

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

MyBatis-plus批量插入的通用方法是什么

这篇文章主要介绍“MyBatis-plus批量插入的通用方法是什么”,在日常操作中,相信很多人在MyBatis-plus批量插入的通用方法是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”MyBatis-p
2023-07-06

MyBatis-plus批量插入的通用方法使用

mybatis-plus的IService接口默认提供saveBatch批量插入,也是唯一一个默认批量插入,在数据量不是很大的情况下可以直接使用,本文带你详细了解MyBatis-plus批量插入的通用方法及使用方法,需要的朋友可以参考一下
2023-05-15

Mybatis-Plus批量插入用法详解

mybatis-plus的IService接口默认提供saveBatch批量插入,也是唯一一个默认批量插入,在数据量不是很大的情况下可以直接使用,但这种是一条一条执行的效率上会有一定的瓶颈,今天我们就来研究研究mybatis-plus中的批量插入
2023-02-15

Mybatis-Plus通过SQL注入器实现批量插入的实践

本文主要介绍了Mybatis-Plus通过SQL注入器实现批量插入的实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2022-11-13

SQL Server批量插入数据的方法是什么

在 SQL Server 中,有几种方法可以进行批量插入数据:1. 使用 INSERT INTO SELECT 语句:可以在一个表中选择数据,然后将其插入到另一个表中。例如:```sqlINSERT INTO destination_tab
2023-09-16

ORACLE大批量插入数据的方法是什么

这篇文章主要介绍了ORACLE大批量插入数据的方法是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇ORACLE大批量插入数据的方法是什么文章都会有所收获,下面我们一起来看看吧。最近有几张表随着时间不断的增长
2023-07-05

mysql的批量插入是什么

这篇文章主要讲解了“mysql的批量插入是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“mysql的批量插入是什么”吧!说明1、批量插入是一种逐条优化数据插入的方式。批量插入数据的语法类
2023-06-20

Mybatis批量插入大量数据的方法有哪些

本文小编为大家详细介绍“Mybatis批量插入大量数据的方法有哪些”,内容详细,步骤清晰,细节处理妥当,希望这篇“Mybatis批量插入大量数据的方法有哪些”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。Mybat
2023-07-05

mysql批量插数据的方法是什么

在MySQL中,可以使用INSERT INTO语句来批量插入数据。以下是一种常用的方法:INSERT INTO table_name (column1, column2, column3) VALUES(value1, value2,
mysql批量插数据的方法是什么
2024-04-09

mybatis-plus配置oracle的方法是什么

要配置MyBatis-Plus来使用Oracle数据库,可以按照以下步骤进行操作:1、首先,在pom.xml文件中添加Oracle数据库驱动的依赖:com.oracle.database.jdb
mybatis-plus配置oracle的方法是什么
2024-03-07

mybatis-plus插入修改配置默认值的实现方式是什么

这篇文章主要介绍“mybatis-plus插入修改配置默认值的实现方式是什么”,在日常操作中,相信很多人在mybatis-plus插入修改配置默认值的实现方式是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答
2023-07-02

【mybatis】mapper.xml中foreach的用法,含批量查询、插入、修改、删除方法的使用

一、xml文件中foreach的主要属性 foreach元素的属性主要有 collection,item,index,separator,open,close。 collection: 表示集合,数据源 item :表示集合中的每一个元素
2023-08-30

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录