mybatis-plus saveBatch插入报错
问题描述
在使用saveBatch
进行插入数据时,报错:
Caused by: java.sql.SQLIntegrityConstraintViolationException: Duplicate entry '12' for key 'article.PRIMARY'
原因分析
- 首先检查报错原因:
article
的主键重复。于是检查 mybatis-plus 打印的日志:
发现插入数据时插入了==> Preparing: INSERT INTO article ( id, title, content, cover_img, state, category_id, create_user, create_time, update_time ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ? )
id
,但由于id
是主键,设置了自增策略。在数据写入数据库时会造成id
的重复。 - 检查插入代码的业务逻辑:
在代码中是先从数据库中取得了之前的数据再进行插入,因此数据已经自带了id
属性,因此需要解决的问题就是在执行saveBatch
插入前先将id
值设置为空。List<Article> articleList = articlepage.getRecords(); articleService.saveBatch(articleList);
解决方法
在执行saveBatch
插入前先将id
值设置为空
List<Article> articleList = articlepage.getRecords();
articleList.stream().forEach(article -> article.setId(null));
articleService.saveBatch(articleList);
需要注意的点(持续更新)
- 进行插入前需要再检查实体类中是否添加了
@TableId
注解:
@TableId(value = "id", type = IdType.AUTO)
标记主键自增,否则插入数据时会生成随机数 - 查看
saveBath
源码,在进行插入逻辑时是一条一条插入,效率比较低,批量插入可以考虑在xml写sql的方法public boolean saveBatch(Collection<T> entityList, int batchSize) { String sqlStatement = this.getSqlStatement(SqlMethod.INSERT_ONE); return this.executeBatch(entityList, batchSize, (sqlSession, entity) -> { sqlSession.insert(sqlStatement, entity); }); }
- 在本项目中,需要执行的业务逻辑是从数据库中取出数据再进行插入。而在实际开发过程中,也需要考虑一下这样的逻辑是否可以改进,是否是必须的步骤。比如:如果数据库中存在的数据已存在就修改,没有就添加,则可以采用
SaveOrUpdate()
方法 - 有些同学可能遇到 即使已经添加了
@TableId
注解,但仍无法实现主键自增。很可能是在 Mybatis-plus 的配置类中没有进行配置public class MybatisPlusConfig { @Bean public GlobalConfig globalConfig() { GlobalConfig config = new GlobalConfig(); config.setDbConfig(new GlobalConfig.DbConfig() .setIdType(IdType.AUTO) // 设置全局主键生成策略为自增 ); return config; } // 其他内容省略 }