引言
在 spring boot + mybatis/mybatis-plus 开发过程中,数据库操作是核心部分之一。然而,由于 sql 语法、数据类型不匹配、约束冲突等问题,开发者经常会遇到 org.springframework.dao.dataintegrityviolationexception
异常。
本文将通过两个典型案例,深入分析 dataintegrityviolationexception
的常见原因,并提供完整的解决方案。同时,我们会结合代码示例,帮助读者理解如何避免类似问题。
1. dataintegrityviolationexception 概述
dataintegrityviolationexception
是 spring 框架在数据库操作失败时抛出的异常,通常由以下原因引起:
- 数据类型不匹配(如字符串插入到 int 列)
- 数据截断(如超长字符串插入 varchar(10))
- 违反约束(如 not null 列插入了 null)
- 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_status
是enum
,但插入了不在枚举列表的值。match_status
是tinyint
,但插入了字符串或超出范围的值(如 256)。match_status
是varchar(10)
,但插入了超长字符串(如"pending_verification"
)。
排查方法:
- 查看表结构:
desc customer_order;
- 检查
match_status
列的定义:
show create table customer_order;
解决方案
情况 1:match_status 是 enum
如果 match_status
是 enum('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_status
是 tinyint
(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_status
是 varchar(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 语法错误、数据类型不匹配或约束冲突引起。通过本文的分析和解决方案,希望读者能够更高效地定位和修复类似问题。
关键点回顾:
- sql 语法检查:确保 update/delete 语句有正确的 where 条件。
- 数据类型匹配:确保 java 代码传入的值与数据库列类型一致。
- 约束校验:避免插入 null、超长或不符合 enum 的值。
以上就是springboot数据库常见错误dataintegrityviolationexception的原因及解决方案的详细内容,更多关于springboot数据库错误dataintegrityviolationexception的资料请关注代码网其它相关文章!
发表评论