Mybatis-Plus save和saveBatch方法忽略自增主键详解
Mybatis-Plus save和saveBatch方法忽略自增主键
这个mybatisplus版本从3.4.0升级到3.5.6之后原来涉及到save和saveBatch方法的地方会报主键冲突
org.springframework.dao.DuplicateKeyException:
### Error updating database. Cause: java.sql.SQLIntegrityConstraintViolationException: Duplicate entry '*' for key '*****.PRIMARY'
各大搜索引擎搜索了一圈,都没有关于这个问题的答案,于是只能跟踪mybatisplus代码进去一探究竟
在MybatisPlusAutoConfiguration创建SqlSessionFactory对象后会
从跟踪情况得知sql语句的生成是在服务启动的时候就加载生成了的。
在MybatisConfiguration类中创建SqlSessionFactory对象
创建过程中遍历mapperLocations使用MybatisXMLMapperBuilder对Mapper文件进行解析,中间步骤跳过,因为我们跟踪的是save和saveBatch这两个方法最终调用的是Mapper.insert方法,所以只需看Insert类即可,上面解析方法为insert通过Insert类来完成
public class Insert extends AbstractMethod {
private boolean ignoreAutoIncrementColumn;
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
KeyGenerator keyGenerator = NoKeyGenerator.INSTANCE;
SqlMethod sqlMethod = SqlMethod.INSERT_ONE;
String columnScript = SqlScriptUtils.convertTrim(tableInfo.getAllInsertSqlColumnMaybeIf((String)null, this.ignoreAutoIncrementColumn), "(", ")", (String)null, ",");
String valuesScript = "(\n" + SqlScriptUtils.convertTrim(tableInfo.getAllInsertSqlPropertyMaybeIf((String)null, this.ignoreAutoIncrementColumn), (String)null, (String)null, (String)null, ",") + "\n" + ")";
String keyProperty = null;
String keyColumn = null;
if (StringUtils.isNotBlank(tableInfo.getKeyProperty())) {
if (tableInfo.getIdType() == IdType.AUTO) {
keyGenerator = Jdbc3KeyGenerator.INSTANCE;
keyProperty = tableInfo.getKeyProperty();
keyColumn = SqlInjectionUtils.removeEscapeCharacter(tableInfo.getKeyColumn());
} else if (null != tableInfo.getKeySequence()) {
keyGenerator = TableInfoHelper.genKeyGenerator(this.methodName, tableInfo, this.builderAssistant);
keyProperty = tableInfo.getKeyProperty();
keyColumn = tableInfo.getKeyColumn();
}
}
String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), columnScript, valuesScript);
SqlSource sqlSource = super.createSqlSource(this.configuration, sql, modelClass);
return this.addInsertMappedStatement(mapperClass, modelClass, this.methodName, sqlSource, (KeyGenerator)keyGenerator, keyProperty, keyColumn);
}
}这个类代码不多,只有一个方法injectMappedStatement,关键代码就在这个方法的columnScript变量赋值上面getAllInsertSqlColumnMaybeIf((String)null, this.ignoreAutoIncrementColumn)
这个方法有个传参ignoreAutoIncrementColumn,是Insert类的成员变量
这个值的默认值是false,在3.4.0的版本中是没有的
3.4.0的版本代码
public class Insert extends AbstractMethod {
public Insert() {
}
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
KeyGenerator keyGenerator = new NoKeyGenerator();
SqlMethod sqlMethod = SqlMethod.INSERT_ONE;
String columnScript = SqlScriptUtils.convertTrim(tableInfo.getAllInsertSqlColumnMaybeIf((String)null), "(", ")", (String)null, ",");
String valuesScript = SqlScriptUtils.convertTrim(tableInfo.getAllInsertSqlPropertyMaybeIf((String)null), "(", ")", (String)null, ",");
String keyProperty = null;
String keyColumn = null;
if (StringUtils.isNotBlank(tableInfo.getKeyProperty())) {
if (tableInfo.getIdType() == IdType.AUTO) {
keyGenerator = new Jdbc3KeyGenerator();
keyProperty = tableInfo.getKeyProperty();
keyColumn = tableInfo.getKeyColumn();
} else if (null != tableInfo.getKeySequence()) {
keyGenerator = TableInfoHelper.genKeyGenerator(this.getMethod(sqlMethod), tableInfo, this.builderAssistant);
keyProperty = tableInfo.getKeyProperty();
keyColumn = tableInfo.getKeyColumn();
}
}
String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), columnScript, valuesScript);
SqlSource sqlSource = this.languageDriver.createSqlSource(this.configuration, sql, modelClass);
return this.addInsertMappedStatement(mapperClass, modelClass, this.getMethod(sqlMethod), sqlSource, (KeyGenerator)keyGenerator, keyProperty, keyColumn);
}
}比3.5.6就少了这个属性,而columnScript赋值的后面方法中如果主键策略是IdType.AUTO也就是自增主键的话默认是不带主键返回的
所以如果3.4.0的版本用了save或saveBatch方法并且带了主键值升级为3.5.6后需要手动设置
mybatis-plus.global-config.db-config.insertIgnoreAutoIncrementColumn=true
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
相关文章
Java通过cellstyle属性设置Excel单元格常用样式的全面总结讲解
在处理Excel文件时,经常需要对单元格进行样式设置,以满足特定的需求和美化要求,这篇文章主要给大家介绍了关于Java通过cellstyle属性设置Excel单元格常用样式的相关资料,需要的朋友可以参考下2024-01-01
SpringBoot配置文件bootstrap和application区别及说明
这篇文章主要介绍了SpringBoot配置文件bootstrap和application区别及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教2024-06-06
SpringBoot实现WebSocket即时通讯的示例代码
本文主要介绍了SpringBoot实现WebSocket即时通讯的示例代码,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下2022-04-04
从零搭建Spring Boot脚手架整合OSS作为文件服务器的详细教程
这篇文章主要介绍了从零搭建Spring Boot脚手架整合OSS作为文件服务器的详细教程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2020-08-08
JetBrains IntelliJ IDEA 2020安装与使用教程详解
这篇文章主要介绍了JetBrains IntelliJ IDEA 2020安装与使用教程,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2020-06-06


最新评论