• mybatis批量插入返回主键ID总是返回最后一个插入的主键ID之解决方式


    项目框架是spring cloud全家桶,引入的mybatis版本如下:

    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>1.3.2</version>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-jdbc</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    

    Dao接口

    int batchInsertCameras(@Param("list") List<Camera> cameras);
    

    Xml文件

    <insert id="batchInsertCameras" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
        insert into camera (camera_type,camera_name)
        values
        <foreach collection="list" item="c" separator=",">
            (#{c.cameraType},#{c.cameraName})
        </foreach>
    </insert>
    
    • useGeneratedKeys:对于支持自动生成记录主键的数据库,如:MySQL,SQL Server,此时设置useGeneratedKeys参数值为true,在执行添加记录之后可以获取到数据库自动生成的主键ID
    • keyColumn:指定数据库主键
    • keyProperty:指定在Java实体类中对应的主键

    代码执行过程(截取了片段)-出问题的所在地!

    // 初始化:批量添加三个相机
    int number = 3;
    // 通过基础信息构建Camera类
    Camera camera = constructCamera(cameraDTO);
    // 构建批量插入所需的Camera集合
    List<Camera> cameraList = new ArrayList<>(number);
    for (int i = 0; i < number; i++) {
        // ******************!!!注意就是这一步,导致问题的出现,后续说明!!!!******************
        cameraList.add(camera);
    }
    // 开始批量插入
    int insertRows = cameraDao.batchInsertCameras(cameraList);
    log.info("批量添加相机成功,添加的数据为:{}", cameraList);
    

    现象1

    传入3个对象的集合进行批量插入,主键ID确实能够将入参赋值成功,但是只返回最后一个成功插入的id 并且赋值给了每记录 ,也就是入参的集合中所有的对象ID都赋值成了最后一个成功插入的ID。官方也是支持批量插入返回主键的啊,为何会出现这种情况呢,妈的思来想去搞了两个小时,调参数啥的,按照网上的方式替换mybatis版本或者加注释啥的,通通不管用。我暂时放弃了,第二天再来分析突然醒悟了,于是写下这篇博客记录一下。

    分析

    1. 通过mybatis底层打断点分析修正。mybatis对主键赋值的操作位置:org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator#processBatch
    2. 根据第一步打了几次断点,内部是循环对集合的每个对象进行主键赋值,发现在第一次赋值的时候,就将所有对象的主键都赋值了,而后的每一次循环赋值,都覆盖了每个对象的主键赋值。
    3. 由第二点我就感觉难不成都是用的同一个对象?操作一个就改变了所有。所以我回头看代码构建插入的入参集合的地方。
    4. 果然!在构建入参集合处,往集合里面add的都是同一个对象,这就导致第2步的问题!
    5. 修正入参集合里面的对象,都为不同对象即可!

    代码修正后

    // 初始化:批量添加三个相机
    int number = 3;
    // 通过基础信息构建Camera类
    Camera camera = constructCamera(cameraDTO);
    // 构建批量插入所需的Camera集合
    List<Camera> cameraList = new ArrayList<>(number);
    for (int i = 0; i < number; i++) {
        // ******************!!!这里是较上次唯一变动的地方!!!!******************
        Camera cameraNew = new Camera();
        BeanUtils.copyProperties(camera, cameraNew);
        cameraList.add(couGet);
    }
    // 开始批量插入
    int insertRows = cameraDao.batchInsertCameras(cameraList);
    log.info("批量添加相机成功,添加的数据为:{}", cameraList);
    

    结果

    成功对每个对象的主键ID赋值,并且赋值正确!直接通过入参的每个对象.getId()就可以获取。

    参考Mybatis赋值主键ID的时序图

  • 相关阅读:
    OpenCV (一)图片读取、修改、保存
    用matplotlib进行数据分析(可视化)
    笔记
    vrpano
    四、threejs——模型交互
    三、threejs不显示英文就是乱码情况,中文解决方案
    二、GLTF模型支持
    一、threejs————灯光阴影
    node的httpserver简单创建
    em和rem区别
  • 原文地址:https://www.cnblogs.com/qukun/p/14211376.html
Copyright © 2020-2023  润新知