通过Mybatis执行拼接的SQL批量插入数据并返回数据库自增ID

Posted Neo-Yang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过Mybatis执行拼接的SQL批量插入数据并返回数据库自增ID相关的知识,希望对你有一定的参考价值。

背景

开发项目引入元数据管理,表和字段都允许用户自己定义。操作数据库的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执行拼接的SQL批量插入数据并返回数据库自增ID的主要内容,如果未能解决你的问题,请参考以下文章

通过Mybatis执行拼接的SQL批量插入数据并返回数据库自增ID

MySQLのmybatis批量插入数据

MyBatis 批量插入的 3 种方式!还有谁不会?

MyBatis 批量插入的 3 种方式!还有谁不会?

[mybatis]动态sql_foreach_遍历集合&批量插入

mybatis批量插入insert时报错