1. 程式人生 > 實用技巧 >mybatis批量插入返回主鍵ID總是返回最後一個插入的主鍵ID之解決方式

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" keyProperty="id">
    insert into camera (camera_type,camera_name)
    values
    <foreach collection="list" item="c" separator=",">
        (#{c.cameraType},#{c.cameraName})
    </foreach>
</insert>

程式碼執行過程(截取了片段)-出問題的所在地!

// 初始化:批量新增三個相機
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賦值,並且賦值正確!