Mybatis-Plus save和saveBatch方法忽略自增主键详解

 更新时间:2025年12月15日 08:45:15   作者:duchx  
Mybatis-Plus在从3.4.0升级到3.5.6后,save和saveBatch方法在处理自增主键时会出现主键冲突的问题,这是因为3.5.6版本中增加了`ignoreAutoIncrementColumn`属性,默认值为false,导致在生成SQL语句时忽略了自增主键,解决方法是手动设置主键值

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单元格常用样式的全面总结讲解

    Java通过cellstyle属性设置Excel单元格常用样式的全面总结讲解

    在处理Excel文件时,经常需要对单元格进行样式设置,以满足特定的需求和美化要求,这篇文章主要给大家介绍了关于Java通过cellstyle属性设置Excel单元格常用样式的相关资料,需要的朋友可以参考下
    2024-01-01
  • java使用电脑摄像头识别二维码

    java使用电脑摄像头识别二维码

    这篇文章主要为大家详细介绍了java使用电脑摄像头识别二维码,从摄像头获取图像,再根据图片解析出二维码信息,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-10-10
  • SpringBoot配置文件bootstrap和application区别及说明

    SpringBoot配置文件bootstrap和application区别及说明

    这篇文章主要介绍了SpringBoot配置文件bootstrap和application区别及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • Java 和 Kotlin Lambda 表达式示例详解

    Java 和 Kotlin Lambda 表达式示例详解

    Lambda 表达式是一种简洁的函数表达方式,可以把函数作为一个方法的参数,或者将代码块转换为数据传递,这篇文章主要介绍了Java 和 Kotlin Lambda 表达式示例详解,需要的朋友可以参考下
    2024-06-06
  • Java一致性Hash算法的实现详解

    Java一致性Hash算法的实现详解

    这篇文章主要介绍了Java一致性Hash算法的实现详解,hash的意思是散列,目的将一组输入的数据均匀的分开、打散,往往用来配合路由算法做负载均衡,多用在分布式系统中,需要的朋友可以参考下
    2024-01-01
  • SpringBoot实现WebSocket即时通讯的示例代码

    SpringBoot实现WebSocket即时通讯的示例代码

    本文主要介绍了SpringBoot实现WebSocket即时通讯的示例代码,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • SpringBoot热部署配置过程

    SpringBoot热部署配置过程

    这篇文章主要介绍了SpringBoot热部署配置过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-03-03
  • 从零搭建Spring Boot脚手架整合OSS作为文件服务器的详细教程

    从零搭建Spring Boot脚手架整合OSS作为文件服务器的详细教程

    这篇文章主要介绍了从零搭建Spring Boot脚手架整合OSS作为文件服务器的详细教程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • JetBrains IntelliJ IDEA 2020安装与使用教程详解

    JetBrains IntelliJ IDEA 2020安装与使用教程详解

    这篇文章主要介绍了JetBrains IntelliJ IDEA 2020安装与使用教程,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-06-06
  • Spring Cloud负载均衡及远程调用实现详解

    Spring Cloud负载均衡及远程调用实现详解

    这篇文章主要介绍了Spring Cloud负载均衡及远程调用实现详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08

最新评论