报错界面:

报错信息:
### Error updating database. Cause: com.mysql.cj.jdbc.exceptions.MysqlDataTruncation: Data truncation: Out of range value for column 'vehicle_quality' at row 1 ### The error may exist in com/xx/ddc/mapper/DdcBrandModelsMapper.java (best guess) ### The error may involve com.xx.ddc.mapper.DdcBrandModelsMapper.insert-Inline ### The error occurred while setting parameters ### SQL: INSERT INTO ddc_brand_models ( id, xx, xxx, xxx, xxx, xxx, certificateno, vehicle_quality, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xxx, xx, xxx, create_by, create_time ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) ### Cause: com.mysql.cj.jdbc.exceptions.MysqlDataTruncation: Data truncation: Out of range value for column 'vehicle_quality' at row 1 ; Data truncation: Out of range value for column 'vehicle_quality' at row 1; nested exception is com.mysql.cj.jdbc.exceptions.MysqlDataTruncation: Data truncation: Out of range value for column 'vehicle_quality' at row 1
一、报错核心含义解析
这个报错是MySQL 数据截断异常(MysqlDataTruncation),核心是向ddc_brand_models表的vehicle_quality列插入的值超出了该列定义的数值 / 长度范围,MySQL 无法存储并触发数据截断,最终导致插入操作失败。拆解关键信息:
- Data truncation: Out of range value for column 'vehicle_quality' at row 1这是核心错误,
vehicle_quality列的插入值超出了其在数据库中定义的取值范围,MySQL 被迫截断数据但仍无法存储; - Error updating database.:表示异常触发在数据库更新(此处为
INSERT插入)阶段; - The error occurred while setting parameters:参数绑定阶段发现值超出列范围,而非 SQL 语法错误;
- 涉及 SQL:向
ddc_brand_models表插入数据时,vehicle_quality的参数值不符合列的定义约束。
简单来说:你要插入的vehicle_quality(车辆质量)数值,超过了数据库中该列设定的类型 / 长度上限,MySQL 拒绝存储并抛出数据截断异常。
二、典型判断
看到该报错可立刻做出以下核心判断:
- 根因是「数据类型 / 范围不匹配」:
vehicle_quality列在数据库中的类型(如tinyint/smallint/int)的取值范围,远小于实际插入的数值; - 非语法 / 连接问题:SQL 语句本身无语法错误,参数绑定也成功,只是数值超出列的物理约束;
- 错误与
vehicle_quality列强相关:只需聚焦该列的数据库定义和插入值的匹配性,无需排查其他列; - 可能的衍生问题:实体类中
vehicle_quality字段的类型设计不合理,或业务层未对输入值做范围校验。
三、常见错误场景
结合 MySQL 数据类型特性和实际开发场景,触发该报错的典型情况如下:
场景 1:数据库列类型的取值范围过小(最常见)
vehicle_quality列被定义为小范围数值类型,但实际插入的车辆质量数值远超其上限。MySQL 常见数值类型的取值范围如下:
| 类型 | 取值范围 | 适用场景 |
|---|---|---|
tinyint | -128 ~ 127(无符号 0~255) | 小整数(如状态值) |
smallint | -32768 ~ 32767(无符号 0~65535) | 中等整数(如数量) |
int | -2147483648 ~ 2147483647 | 常规整数(如 ID、金额) |
bigint | -9e18 ~ 9e18 | 大整数(如超大计数) |
示例:
- 数据库中
vehicle_quality定义为tinyint(无符号,最大值 255),但插入的车辆质量是1500(千克),远超 255 的上限; - 列定义为
smallint(最大值 32767),但插入了50000,超出范围。
场景 2:实体类字段类型与数据库列类型不匹配(间接触发)
Java 实体类中vehicle_quality字段的类型为大数值类型(如Long/Double),但数据库列是小范围类型(如smallint),业务层传入大数值时直接超出列范围。示例:
java
运行
// 实体类
public class DdcBrandModels {
private Long vehicleQuality; // 类型为Long,可存储大数值
}
// 数据库列定义:vehicle_quality SMALLINT(5) // 最大值32767
// 插入值:vehicleQuality = 50000L → 超出smallint范围,触发报错
场景 3:数值单位不匹配导致范围溢出
设计表时对vehicle_quality的单位定义错误,导致实际值按错误单位存储时超出范围。示例:
- 设计时计划用「克」为单位,列定义为
int(可存最大 21 亿),但业务层实际传入「千克」(如 1500 千克 = 1500000 克,本应存 1500000,却错误存了 15000000000,超出 int 上限); - 反之,列按「千克」设计为
smallint(最大 32767),但业务层传入「克」(1500 千克 = 1500000 克),超出范围。
场景 4:小数插入整数列导致截断(特殊情况)
vehicle_quality列定义为整数类型(如int),但插入的值是小数(如1500.5),MySQL 尝试自动转换时若小数部分导致数值超出整数范围,或直接因 “非整数” 触发截断(取决于sql_mode)。示例:
- 列定义为
tinyint(最大值 255),插入255.1,MySQL 转换为256后超出范围,触发报错; - 若
sql_mode开启STRICT_TRANS_TABLES(严格模式),插入小数到整数列会直接触发数据截断异常。
场景 5:数据库列的DECIMAL精度 / 标度设置不足
若vehicle_quality列定义为DECIMAL(p,s)(定点数),但插入的数值超出其精度(p,总位数)或标度(s,小数位数)范围。示例:
- 列定义为
DECIMAL(5,2)(总位数 5,小数 2 位,最大值999.99),插入1000.00(整数部分占 4 位,总位数 6),超出精度范围触发报错。
四、处理办法(分步解决)
步骤 1:查看vehicle_quality列的数据库定义
通过数据库客户端(Navicat/DBeaver/MySQL 命令行)执行以下 SQL,获取该列的具体类型和约束:
sql
-- 查看表结构
DESC ddc_brand_models;
-- 或更详细的列信息
SELECT COLUMN_NAME, DATA_TYPE, NUMERIC_PRECISION, NUMERIC_SCALE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'ddc_brand_models' AND COLUMN_NAME = 'vehicle_quality';
重点关注:列的类型(tinyint/smallint/int/decimal)、是否无符号(UNSIGNED)、精度 / 标度(若为DECIMAL)。
步骤 2:核对插入的vehicle_quality具体值
通过日志 / 调试模式获取插入的vehicle_quality实际数值,确认是否超出步骤 1 中列的取值范围:
- 若使用 MyBatis,开启 SQL 日志打印参数值(在
application.yml中配置logging.level.你的mapper包=DEBUG); - 若在业务层,通过
System.out.println/ 日志输出插入前的vehicle_quality值。
步骤 3:修改数据库列类型为合适的范围(核心解决)
根据实际业务的车辆质量数值范围,调整vehicle_quality列的类型:
sql
-- 示例1:若车辆质量范围在0~10000千克,改为int(无符号)
ALTER TABLE ddc_brand_models MODIFY COLUMN vehicle_quality INT UNSIGNED COMMENT '车辆质量(千克)';
-- 示例2:若需存储小数(如1500.5千克),改为DECIMAL(10,2)(总位数10,小数2位)
ALTER TABLE ddc_brand_models MODIFY COLUMN vehicle_quality DECIMAL(10,2) COMMENT '车辆质量(千克)';
-- 示例3:若数值极大,改为bigint
ALTER TABLE ddc_brand_models MODIFY COLUMN vehicle_quality BIGINT COMMENT '车辆质量';
注意:修改列类型前需备份表数据,避免数据丢失;若表中已有数据,确保新类型能兼容原有数据。
步骤 4:业务层增加数据范围校验(避免再次触发)
在插入数据前,对vehicle_quality做范围校验,防止超出数据库列的取值范围:
java
运行
// 实体类
public class DdcBrandModels {
private Integer vehicleQuality; // 与数据库列类型匹配
// 可选:添加字段校验注解(如使用Spring Validation)
@Max(value = 100000, message = "车辆质量不能超过100000千克")
@Min(value = 0, message = "车辆质量不能为负数")
public Integer getVehicleQuality() {
return vehicleQuality;
}
}
// Service层
@Service
public class DdcBrandModelsServiceImpl implements DdcBrandModelsService {
@Override
public int insertDdcBrandModels(DdcBrandModels ddcBrandModels) {
// 手动校验(若未用注解校验)
Integer quality = ddcBrandModels.getVehicleQuality();
if (quality == null || quality < 0 || quality > 100000) {
throw new IllegalArgumentException("车辆质量超出合法范围(0~100000千克)");
}
return ddcBrandModelsMapper.insert(ddcBrandModels);
}
}
步骤 5:修正实体类与数据库列的类型映射
确保 Java 实体类中vehicle_quality的字段类型与数据库列类型一致:
| 数据库列类型 | 推荐 Java 类型 |
|---|---|
tinyint | Byte/Integer |
smallint | Short/Integer |
int | Integer |
bigint | Long |
decimal | BigDecimal |
示例:数据库列是DECIMAL(10,2),实体类字段应为BigDecimal:
java
运行
private BigDecimal vehicleQuality;
五、避免方式(规范开发减少问题)
-
表结构设计时合理选择数据类型
- 针对业务场景预估字段的取值范围,选择足够大但不冗余的类型(如车辆质量用
int而非tinyint,金额用DECIMAL(10,2)而非float); - 对数值型字段明确单位(如千克 / 克),并在列注释中注明,避免单位混淆导致的范围错误。
- 针对业务场景预估字段的取值范围,选择足够大但不冗余的类型(如车辆质量用
-
实体类与数据库列类型严格匹配
- 遵循「数据库类型→Java 类型」的映射规范,避免用
Long接收数据库int列、用Integer接收decimal列; - 利用代码生成器(如 MyBatis Generator、若依代码生成器)自动生成实体类,减少手动映射错误。
- 遵循「数据库类型→Java 类型」的映射规范,避免用
-
业务层强制数据校验
- 使用 Spring Validation(
@Max/@Min/@DecimalMax等注解)或手动校验,对数值字段做范围限制; - 前端页面也需添加输入限制(如输入框最大值、正则校验),从源头拦截非法值。
- 使用 Spring Validation(
-
开启 MySQL 严格模式在
my.cnf/my.ini中开启sql_mode=STRICT_TRANS_TABLES,让 MySQL 在数据截断时直接抛出异常(而非静默截断),便于开发阶段及时发现问题:ini
[mysqld] sql_mode = STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION -
测试覆盖边界值场景开发时对数值字段的最小值、最大值、临界值做测试(如车辆质量的 0、列上限值、超上限值),验证数据库和业务层的约束是否生效。
-
避免硬编码数值范围将数值范围配置在配置文件(如
application.yml)中,便于后续调整:yaml
business: vehicle: quality: min: 0 max: 100000业务层读取配置做校验,避免硬编码导致的修改繁琐。

214

被折叠的 条评论
为什么被折叠?



