mybatis批量插入返回主鍵ID總是返回最後一個插入的主鍵ID之解決方式
阿新 • • 發佈:2020-12-30
專案框架是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版本或者加註釋啥的,通通不管用。我暫時放棄了,第二天再來分析突然醒悟了,於是寫下這篇部落格記錄一下。
分析
- 通過mybatis底層打斷點分析修正。mybatis對主鍵賦值的操作位置:org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator#processBatch
- 根據第一步打了幾次斷點,內部是迴圈對集合的每個物件進行主鍵賦值,發現在第一次賦值的時候,就將所有物件的主鍵都賦值了,而後的每一次迴圈賦值,都覆蓋了每個物件的主鍵賦值。
- 由第二點我就感覺難不成都是用的同一個物件?操作一個就改變了所有。所以我回頭看程式碼構建插入的入參集合的地方。
- 果然!在構建入參集合處,往集合裡面add的都是同一個物件,這就導致第2步的問題!
- 修正入參集合裡面的物件,都為不同物件即可!
程式碼修正後
// 初始化:批量新增三個相機
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賦值,並且賦值正確!