SpringBoot数据库常见错误DataIntegrityViolationException的原因及解决方案

 更新时间:2025年07月14日 10:28:06   作者:码农阿豪@新空间  
在SpringBoot+MyBatis/MyBatis-Plus开发过程中,数据库操作是核心部分之一,然而,开发者经常会遇到 org.springframework.dao.DataIntegrityViolationException异常本文将通过两个典型案例,深入分析DataIntegrityViolationException的常见原因,并提供完整的解决方案

引言

在 Spring Boot + MyBatis/MyBatis-Plus 开发过程中,数据库操作是核心部分之一。然而,由于 SQL 语法、数据类型不匹配、约束冲突等问题,开发者经常会遇到 org.springframework.dao.DataIntegrityViolationException 异常。

本文将通过两个典型案例,深入分析 DataIntegrityViolationException 的常见原因,并提供完整的解决方案。同时,我们会结合代码示例,帮助读者理解如何避免类似问题。

1. DataIntegrityViolationException 概述

DataIntegrityViolationException 是 Spring 框架在数据库操作失败时抛出的异常,通常由以下原因引起:

  1. 数据类型不匹配(如字符串插入到 INT 列)
  2. 数据截断(如超长字符串插入 VARCHAR(10))
  3. 违反约束(如 NOT NULL 列插入了 NULL)
  4. SQL 语法错误(如 UPDATE 语句缺少 WHERE 条件)

接下来,我们通过两个实际案例进行分析。

2. 案例 1:SQL 语法错误导致的数据类型转换异常

问题描述

在执行以下 MyBatis XML 映射的 SQL 时,报错:

org.springframework.dao.DataIntegrityViolationException: 
### Error updating database. Cause: com.mysql.cj.jdbc.exceptions.MysqlDataTruncation: 
Data truncation: Truncated incorrect DOUBLE value: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...'

错误 SQL:

<update id="updateCookie">
    update task_management set cookie = #{cookie}
    <if test="creatorId != null">
        and creator_id = #{creatorId}
    </if>
</update>

问题分析

错误原因:

  • SQL 语句缺少 WHERE 关键字,导致 and creator_id = #{creatorId} 被解析为 cookie = (#{cookie} and creator_id = #{creatorId})
  • MySQL 尝试将 JWT Token(字符串)和 creatorId 进行逻辑运算,导致类型转换失败。

错误 SQL 实际执行情况:

-- 错误的 SQL
UPDATE task_management SET cookie = ('eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...' AND creator_id = 123);

-- 正确的 SQL 应该是
UPDATE task_management SET cookie = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...' WHERE creator_id = 123;

解决方案

方法 1:使用 <where> 标签

<update id="updateCookie">
    UPDATE task_management
    SET cookie = #{cookie}
    <where>
        <if test="creatorId != null">
            AND creator_id = #{creatorId}
        </if>
    </where>
</update>

方法 2:使用 <trim> 标签

<update id="updateCookie">
    UPDATE task_management
    SET cookie = #{cookie}
    <trim prefix="WHERE" prefixOverrides="AND">
        <if test="creatorId != null">
            AND creator_id = #{creatorId}
        </if>
    </trim>
</update>

方法 3:使用注解方式

@Update("<script>" +
        "UPDATE task_management SET cookie = #{cookie}" +
        "<where>" +
        "   <if test='creatorId != null'>AND creator_id = #{creatorId}</if>" +
        "</where>" +
        "</script>")
void updateCookie(@Param("cookie") String cookie, @Param("creatorId") Long creatorId);

最佳实践

  • 始终在 UPDATE/DELETE 语句中使用 WHERE 条件,避免全表更新。
  • 使用 MyBatis 动态 SQL 标签(<where><trim>)防止语法错误。
  • 启用 SQL 日志,检查实际执行的 SQL:
logging.level.org.mybatis=DEBUG

3. 案例 2:数据截断错误(Data Truncation)

问题描述

在插入数据时,报错:

org.springframework.dao.DataIntegrityViolationException:
### Error updating database. Cause: java.sql.SQLException: 
Data truncated for column 'match_status' at row 1

错误 SQL:

INSERT INTO customer_order (match_status) VALUES ('pending_verification');

问题分析

可能原因:

  • match_statusENUM,但插入了不在枚举列表的值。
  • match_statusTINYINT,但插入了字符串或超出范围的值(如 256)。
  • match_statusVARCHAR(10),但插入了超长字符串(如 "pending_verification")。

排查方法:

  • 查看表结构:
DESC customer_order;
  • 检查 match_status 列的定义:
SHOW CREATE TABLE customer_order;

解决方案

情况 1:match_status 是 ENUM

如果 match_statusENUM('pending', 'success', 'failed'),则只能插入这三个值之一:

ALTER TABLE customer_order 
MODIFY COLUMN match_status ENUM('pending', 'success', 'failed') NOT NULL;

代码调整:

customerOrder.setMatchStatus("success"); // 正确
// customerOrder.setMatchStatus("invalid_status"); // 错误

情况 2:match_status 是 TINYINT

如果 match_statusTINYINT(0-255),则不能插入字符串或超出范围的值:

ALTER TABLE customer_order 
MODIFY COLUMN match_status TINYINT UNSIGNED NOT NULL DEFAULT 0;

代码调整:

customerOrder.setMatchStatus(1); // 正确
// customerOrder.setMatchStatus(256); // 错误(超出范围)
// customerOrder.setMatchStatus("pending"); // 错误(类型不匹配)

情况 3:match_status 是 VARCHAR 但长度不足

如果 match_statusVARCHAR(10),但插入了更长的字符串:

ALTER TABLE customer_order 
MODIFY COLUMN match_status VARCHAR(50); -- 扩大长度

代码调整:

customerOrder.setMatchStatus("pending"); // 正确
// customerOrder.setMatchStatus("pending_verification"); // 可能被截断

最佳实践

  • 在数据库设计阶段明确字段类型和约束。
  • 在代码中校验数据是否符合数据库约束。
  • 使用日志监控 SQL 执行情况:
logging.level.org.springframework.jdbc=DEBUG

4. 总结与预防措施

问题类型错误示例解决方案
SQL 语法错误UPDATE ... SET col = val AND ...使用 <where> 标签
ENUM 不匹配插入不在枚举列表的值修改数据库或代码
数值超出范围TINYINT 插入 256检查数据库范围
字符串超长VARCHAR(10) 插入 20 字符扩大列长度或截断数据

通用调试技巧

查看数据库表结构:

DESC table_name;
SHOW CREATE TABLE table_name;

启用 SQL 日志:

logging.level.org.mybatis=DEBUG
logging.level.org.springframework.jdbc=DEBUG

在代码中校验数据:

if (value.length() > 10) {
    throw new IllegalArgumentException("字段超长");
}

5. 结语

DataIntegrityViolationException 是 Spring Boot 开发中常见的数据库异常,通常由 SQL 语法错误、数据类型不匹配或约束冲突引起。通过本文的分析和解决方案,希望读者能够更高效地定位和修复类似问题。

关键点回顾:

  1. SQL 语法检查:确保 UPDATE/DELETE 语句有正确的 WHERE 条件。
  2. 数据类型匹配:确保 Java 代码传入的值与数据库列类型一致。
  3. 约束校验:避免插入 NULL、超长或不符合 ENUM 的值。

以上就是SpringBoot数据库常见错误DataIntegrityViolationException的原因及解决方案的详细内容,更多关于SpringBoot数据库错误DataIntegrityViolationException的资料请关注脚本之家其它相关文章!

相关文章

  • 使用自定义注解和@Aspect实现责任链模式的组件增强的详细代码

    使用自定义注解和@Aspect实现责任链模式的组件增强的详细代码

    责任链模式是一种行为设计模式,其作用是将请求的发送者和接收者解耦,从而可以灵活地组织和处理请求,本文讲给大家介绍如何使用自定义注解和@Aspect实现责任链模式的组件增强,文中有详细的代码示例供大家参考,感兴趣的同学可以借鉴一下
    2023-05-05
  • springAOP完整实现过程

    springAOP完整实现过程

    当你调用SimpleService类的doSomething方法时,上述的PerformanceAspect会自动拦截此调用,并且记录该方法的执行时间,这样你就完成了一个针对Spring的AOP入门级案例,感兴趣的朋友一起看看吧
    2024-02-02
  • Java DelayQueue实现延时任务的示例详解

    Java DelayQueue实现延时任务的示例详解

    DelayQueue是一个无界的BlockingQueue的实现类,用于放置实现了Delayed接口的对象,其中的对象只能在其到期时才能从队列中取走。本文就来利用DelayQueue实现延时任务,感兴趣的可以了解一下
    2022-08-08
  • 关于SpringBoot中事务失效的几种情况

    关于SpringBoot中事务失效的几种情况

    这篇文章主要介绍了关于SpringBoot中事务失效的几种情况,Spring AOP默认使用动态代理,会给被代理的类生成一个代理类,事务相关的操作都通过代理来完成,使用内部方法调用时,使用的是实例调用,没有通过代理类调用方法,因此事务不会检测到失败,需要的朋友可以参考下
    2023-08-08
  • 用java在web环境下上传和下载文件的技巧

    用java在web环境下上传和下载文件的技巧

    这篇文章主要介绍了用java在web环境下上传和下载文件的技巧的相关资料
    2016-01-01
  • springboot中spring.profiles.include的妙用分享

    springboot中spring.profiles.include的妙用分享

    这篇文章主要介绍了springboot中spring.profiles.include的妙用,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • IDEA集成Sonar的完整流程

    IDEA集成Sonar的完整流程

    这篇文章主要介绍了IDEA集成Sonar的完整流程,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • Netty分布式行解码器逻辑源码解析

    Netty分布式行解码器逻辑源码解析

    这篇文章主要为大家介绍了Netty分布式行解码器逻辑源码解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-03-03
  • Mybatis-plus中的@EnumValue注解使用详解

    Mybatis-plus中的@EnumValue注解使用详解

    这篇文章主要介绍了Mybatis-plus中的@EnumValue注解使用详解,在PO类中,如果我们直接使用枚举类型去映射数据库的对应字段保存时,往往就会因为类型不匹配导致映射失败,Mybatis-plus提供了一种解决办法,就是使用@EnumValue注解,需要的朋友可以参考下
    2024-02-02
  • Java集合框架之Set的实现类与实战使用详解

    Java集合框架之Set的实现类与实战使用详解

    本文深入解析Java集合框架中的Set接口及其实现类,重点内容包括Set接口不可重复性和无序性的设计理念,HashSet基于哈希表的底层实现与去重机制,LinkedHashSet维护插入顺序的原理等,需要的朋友可以参考下
    2026-02-02

最新评论