通过mybatis执行拼接的sql批量插入数据并返回数据库自增id(代码片段)

Neo-Yang Neo-Yang     2022-12-10     637

关键词:

背景

开发项目引入元数据管理,表和字段都允许用户自己定义。操作数据库的SQL就不能在mybatis 的xml文件里面写具体的表名和子段名。

解决这个问题有两种思路,一种是用PreparedStatement组装SQL语句通过JDBC连接执行;另一种是将表名,字段名称作为参数传递到mybatis执行。

这里描述第二种方案中比较复杂的批量插入数据怎么实现。

首先在MySQL中创建一个简单的t_user表。其DDL如下所示:

CREATE TABLE `t_user` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT '',
  `age` int DEFAULT '20',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=25 DEFAULT CHARSET=utf8mb3 COMMENT='用户表'

定义DAO层接口

1. 访问数据库的mapper接口

package com.elon.mapper;

import com.elon.model.InsertValueModel;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.util.List;

/**
 * 动态数据查询接口
 *
 * @author elon
 * @since 2022-02-19
 */
@Mapper
public interface DataMapper 
    /**
     * 批量插入数据
     *
     * @param fieldNameList 数据库字段名称列表
     * @param tableName     数据库表名
     * @param bulkDataList  数据库多行数据
     * @author elon
     */
    void batchInsertData(@Param("fieldNameList") List<String> fieldNameList,
                     @Param("tableName") String tableName,
                     @Param("list") List<InsertValueModel> bulkDataList);

注意:bulkDataList参数注解固定写为:@Param(“list”) 。

2. 定义插入数据的模型

InsertValueModel模型每个实例代表数据库的一行记录。为了接收回填的自增ID,增加一个id成员。

package com.elon.model;

import lombok.Getter;
import lombok.Setter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 单条插入数据库的数据
 *
 * @author elon
 * @since 2022-02-19
 */
@Getter
@Setter
public class InsertValueModel 
    /**
     * 用于接收回填的自增ID
     */
    private int id = -1;

    /**
     * 数据列表
     */
    private List<Object> dataList = new ArrayList<>();

    public static InsertValueModel create(Object... values) 
        InsertValueModel valueModel = new InsertValueModel();
        valueModel.dataList = Arrays.asList(values);
        return valueModel;
    


增加Mybatis的XML文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.elon.mapper.DataMapper">
    <!--批量插入数据-->
    <insert id="batchInsertData" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
        INSERT INTO $tableName
        <foreach item = "field" collection="fieldNameList" open="(" separator="," close=")">
            $field
        </foreach>
        VALUES
        <foreach item="record" collection="list" separator=",">
            <foreach item="data" collection="record.dataList" open="(" separator="," close=")">
                #data
            </foreach>
        </foreach>
    </insert>
</mapper>
这里要注意两点:

1. 配置用于回填自增ID属性: keyProperty="id"。

2. 用于拼接insert语句的数据集合指定为list: collection="list"。

测试接口,打印回填的自增ID

1. 测试接口代码

@RestController
@RequestMapping("/v1/user")
@Api(tags = "测试接口")
public class UserController 
    private static Logger LOGGER = LoggerFactory.getLogger(UserController.class);
    
    @Resource
    private DataMapper dataMapper;
    
    @PostMapping("bulk-insert-user-data")
    @ApiOperation(value = "批量插入用户数据")
    public List<Integer> bulkInsertUserData() 
        // 初始化拼接SQL用的表名和字段名
        List<String> fieldNameList = Arrays.asList("name", "age");
        String tableName = "t_user";

        // 初始化批量数据
        List<InsertValueModel> bulkDataList = new ArrayList<>();
        bulkDataList.add(InsertValueModel.create("张三", 12));
        bulkDataList.add(InsertValueModel.create("李四", 15));
        bulkDataList.add(InsertValueModel.create("王五", 19));

        dataMapper.batchInsertData(fieldNameList, tableName, bulkDataList);

        List<Integer> ids = bulkDataList.stream().map(InsertValueModel::getId).collect(Collectors.toList());
        LOGGER.info("打印自增ID:", ids);
        return ids;
    

2. 用swagger调用一下上面的测试接口,可以看到打印的结果

2022-02-19 16:13:57,932 INFO c.z.h.HikariDataSource [http-nio-10001-exec-5] HikariPool-1 - Start completed.
2022-02-19 16:13:58,363 INFO c.e.r.UserController [http-nio-10001-exec-5] 打印自增ID:[25, 26, 27]

测试代码github路径: https://github.com/ylforever/elon-mybatisxml.git

mybatis批量插入数据的两种方式(代码片段)

...息框架。使用批量插入技术能提升数据持久化的性能。用mybatis有两种批量插入数据的方式可选:1.拼接批量插入多条数据的SQL.2.使用BatchInsert技术。方式一:拼接插入多条数据的SQLmapper接口代码/***插入数据列表**@paramda... 查看详情

mybatis批量插入数据的3种方法!

‍‍先来简单说一下3种批量插入功能分别是:循环单次插入;MP批量插入功能;原生批量插入功能。 准备工作开始之前我们先来创建数据库和测试数据,执行的SQL脚本如下:-- ------------------------------ 创建数... 查看详情

mybatis批量插入的方式

批量插入数据经常是把一个集合的数据一次性插入数据库,只需要执行一次sql语句,但是批量插入通常会报框架版本号的错误,本人就遇到 com.alipay.zdal.parser.exceptions.a:ERROR##getsqlparserresultfromcachehasanerror:的错误,项目使用的是... 查看详情

mybatis批量插入数据性能测试(代码片段)

目录1、准备2、普通for循环批量插入数据测试3、使用MyBatis提供的BATCH模式4、mybatis中直接使用foreach插入数据5、mybatis如何开启batch模式for循环测试批量插入和更新数据,myabtis的Batch模式,mybatis中直接使用foreachsql拼接插入... 查看详情

mybatis批量插入的3种方式!还有谁不会?(代码片段)

来自:简书,作者: 楼主楼主链接:https://www.jianshu.com/p/cce617be9f9e数据库使用的是sqlserver,JDK版本1.8,运行在SpringBoot环境下,对比3种可用的方式:反复执行单条插入语句xml拼接sql批处理执行先说... 查看详情

mybatis的批量处理功能

由于在3.1.1升级后,可直接通过batchExcutor实现具体的批量执行。在该excutor中会重用上一次相同的prepareStatement。/***批量插入数据<br/>*1、数据批量插入,默认一次提交100条,当发生异常后继续提交异常行以后的数据,待集合全... 查看详情

javaweb学习笔记之mybatis实用sql语句汇总(代码片段)

一、批量插入/更新/删除批量操作主要使用的是Mybatis的foreach,遍历参数列表执行相应的操作,所以批量插入/更新/删除的写法是类似的,只是SQL略有区别而已。MySql批量操作需要数据库连接配置allowMultiQueries=true才... 查看详情

mybatis批量插入

第四章mybatis批量insert批量插入sql语句:INSERTINTOtable(field1,field2,field3)VALUES(‘a‘,"b","c"),(‘a‘,"b","c"),(‘a‘,"b","c")mybatis通过foreach循环拼装了如上的sql语句。一、xml复制代码1<?xmlversion="1.0"encoding="UTF-8"?>2<! 查看详情

mybatis如何执行批量插入数据?(代码片段)

首先,创建一个简单的insert语句:<insertid=”insertname”>insertintonames(name)values(#value)</insert>然后在java代码中像下面这样执行批处理插入:list<string>names=newarraylist();names.add(“fred”);names.add(“b 查看详情

mybatis-plus的批量新增insertbatchsomecolumn(代码片段)

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

mybatis的foreach批量模糊like查询及批量插入

使用mybatis平时都是用遍历集合in()…,其实还可以多模糊查询和批量操作等其他操作,要明白foreach元素的属性主要意义,灵活使用,举例如下。1、根据多个品牌名字分类,模糊搜索数据,主要利用separator&#... 查看详情

sql笔记--mysql高级操作

...现有SQL操作,即便数据表已经存在数据,但是我们也无法通过SQL实现,只能取出来后通过其他代码对数据进行加工实现通过高级SQL学习,我们就可以通过一条SQL指令完成操作selectcount(*),班级IDfrom学生表groupby班级ID;一、数据新增... 查看详情

java通过mybatis实现批量插入数据到oracle中

最近项目中遇到一个问题:导入数据到后台并将数据插入到数据库中,导入的数据量有上万条数据,考虑采用批量插入数据的方式;结合网上资料,写了个小demo,文章末尾附上demo下载地址1、新建项目:项目目录结构如下图所示... 查看详情

javaweb学习笔记之mybatis实用sql语句汇总(代码片段)

一、批量插入/更新/删除批量操作主要使用的是Mybatis的foreach,遍历参数列表执行相应的操作,所以批量插入/更新/删除的写法是类似的,只是SQL略有区别而已。MySql批量操作需要数据库连接配置allowMultiQueries=true才... 查看详情

mybatis的foreach批量模糊like查询及批量插入(代码片段)

使用mybatis平时都是用遍历集合in()…,其实还可以多模糊查询和批量操作等其他操作,要明白foreach元素的属性主要意义,灵活使用,举例如下。1、根据多个品牌名字分类,模糊搜索数据,主要利用separator&#... 查看详情

mybatis+mysql批量插入和批量更新

一、批量插入批量插入数据使用的sql语句是:insertintotable(字段一,字段二,字段三)values(xx,xx,xx),(oo,oo,oo) mybatis中mapper.xml的代码如下:  <!--批量插入数据--><insertid="insertBatch"parameterType="java.util.List"useGeneratedKeys 查看详情

mybatis批量操作数据

参考技术Amybatis的批量操作有两种方式,一是使用foreach标签,二是使用mybatis的BATCH模型在xml中通过foreach对表数据进行循环操作在oracle中不支持insertintoproduct(name,type,price)values(\'a\',\'tv\',1233),(\'b\',\'ac\',3455),....(\'\',\'\',\'\')这种形式... 查看详情

mybatis批量插入数据的两种方式(代码片段)

总体描述软件开发过程中需要批量插入数据的场景有几种:从离线文件(excel,csv等)导入大批量数据到系统。从其它系统定时或者人工同步大批量数据到系统。程序自身的某些算法执行时会生成大批量数据保存到数据库。... 查看详情