场景:
使用mybatis-plus进行批量插入,由于一次错误的写法,导致在版本V3.5.0之前的版本中可以插入,没有发生主键冲突的问题,但是在V3.5.0之后的版本中进行批量插入的时候发生了主键冲突的问题,错误用法如下:
@Test
@Transactional(rollbackFor = Exception.class)
public void testBatchInsert() {
List<TUser> list = new ArrayList<>();
for (int i = 0; i < 5; i ++) {
TUser tUser = new TUser();
tUser.setUserName("yy" + i);
tUser.setPassword("pp" + i);
list.add(tUser);
userService.saveBatch(list);
}
}
分析:
分析上面的错误,由于误将saveBatch方法执行时机放到了for循环里面,导致循环进行插入的时候,第一次插入的TUser对象完成saveBatch操作之后,在list中该对象的id字段就有值了(这里TUser的id字段是自增) ,第二次再将该id有值的对象进行saveBatch操作的时候,如果是在V3.5.0之前的版本是可以插入,不会报错,但是在V3.5.0之后的版本里面是会产生主键冲突的异常,这是因为第一次saveBatch操作产生了id,第二次saveBatch操作先将没有id的对象保存这时的id还是根据数据库里已经提交的记录的最新id递增的,会和第一次saveBatch产生的id冲突
另外,从saveBatch底层代码的逻辑可以看出,它的批量保存本质还是拆解成一条一条的insert语句进行保存
解决方案:
将mybatis的依赖版本从3.5.0之前的版本升级到3.5.0之后的版本如下:
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.1</version> </dependency>