Mybatis-Plus save和saveBatch方法忽略自增主鍵詳解
Mybatis-Plus save和saveBatch方法忽略自增主鍵
這個(gè)mybatisplus版本從3.4.0升級(jí)到3.5.6之后原來(lái)涉及到save和saveBatch方法的地方會(huì)報(bào)主鍵沖突
org.springframework.dao.DuplicateKeyException:
### Error updating database. Cause: java.sql.SQLIntegrityConstraintViolationException: Duplicate entry '*' for key '*****.PRIMARY'
各大搜索引擎搜索了一圈,都沒(méi)有關(guān)于這個(gè)問(wèn)題的答案,于是只能跟蹤mybatisplus代碼進(jìn)去一探究竟
在MybatisPlusAutoConfiguration創(chuàng)建SqlSessionFactory對(duì)象后會(huì)
從跟蹤情況得知sql語(yǔ)句的生成是在服務(wù)啟動(dòng)的時(shí)候就加載生成了的。
在MybatisConfiguration類中創(chuàng)建SqlSessionFactory對(duì)象
創(chuàng)建過(guò)程中遍歷mapperLocations使用MybatisXMLMapperBuilder對(duì)Mapper文件進(jìn)行解析,中間步驟跳過(guò),因?yàn)槲覀兏櫟氖莝ave和saveBatch這兩個(gè)方法最終調(diào)用的是Mapper.insert方法,所以只需看Insert類即可,上面解析方法為insert通過(guò)Insert類來(lái)完成
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);
}
}這個(gè)類代碼不多,只有一個(gè)方法injectMappedStatement,關(guān)鍵代碼就在這個(gè)方法的columnScript變量賦值上面getAllInsertSqlColumnMaybeIf((String)null, this.ignoreAutoIncrementColumn)
這個(gè)方法有個(gè)傳參ignoreAutoIncrementColumn,是Insert類的成員變量
這個(gè)值的默認(rèn)值是false,在3.4.0的版本中是沒(méi)有的
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就少了這個(gè)屬性,而columnScript賦值的后面方法中如果主鍵策略是IdType.AUTO也就是自增主鍵的話默認(rèn)是不帶主鍵返回的
所以如果3.4.0的版本用了save或saveBatch方法并且?guī)Я酥麈I值升級(jí)為3.5.6后需要手動(dòng)設(shè)置
mybatis-plus.global-config.db-config.insertIgnoreAutoIncrementColumn=true
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- mybatis-plus如何根據(jù)任意字段saveOrUpdateBatch
- MyBatis-Plus:saveOrUpdate根據(jù)指定字段更新或插入方式
- mybatis-plus saveOrUpdateBatch踩坑記錄
- Mybatis-Plus的saveOrUpdateBatch(null)問(wèn)題及解決
- 怎樣提高mybatis-plus中saveBatch方法的效率
- mybatis-plus 關(guān)于savebatch,saveorupdatebatch遇到的坑及解決辦法
- Mybatis-Plus saveBatch()批量保存失效的解決
- Mybatis-Plus使用saveOrUpdate及問(wèn)題解決方法
相關(guān)文章
Java 回調(diào)機(jī)制(CallBack) 詳解及實(shí)例代碼
這篇文章主要介紹了 Java 回調(diào)機(jī)制(CallBack) 詳解及實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2017-02-02
Java實(shí)現(xiàn)上傳和下載功能(支持多個(gè)文件同時(shí)上傳)
這篇文章主要介紹了Java實(shí)現(xiàn)上傳和下載功能,支持多個(gè)文件同時(shí)上傳,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-12-12
Java執(zhí)行shell命令的實(shí)現(xiàn)
本文主要介紹了Java執(zhí)行shell命令的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01
Mybatis-Plus自動(dòng)生成id涉及的問(wèn)題解決過(guò)程
文章主要講述了解決用戶ID在頁(yè)面和數(shù)據(jù)庫(kù)中不一致的問(wèn)題,并提供了兩種解決方案:將主鍵類型改為String或刪除數(shù)據(jù)庫(kù)表重新創(chuàng)建以清空最大id2025-12-12
springmvc中進(jìn)行數(shù)據(jù)保存以及日期參數(shù)的保存過(guò)程解析
這篇文章主要介紹了springmvc中進(jìn)行數(shù)據(jù)保存以及日期參數(shù)的保存過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09
解釋為什么Java中“1000==1000”為false而”100==100“為true
在日常編程中,我們經(jīng)常遇到一些看似簡(jiǎn)單卻隱藏著復(fù)雜邏輯的問(wèn)題,這篇文章主要介紹了解釋為什么Java中“1000==1000”為false而”100==100“為true,需要的朋友可以參考下2024-01-01

