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的時序圖


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM