MySQL常见报错分析及解决方案总结(38)---Data truncation: Out of range value for column ‘vehicle_quality‘ at row 1

报错界面:

报错信息:

### 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 无法存储并触发数据截断,最终导致插入操作失败。拆解关键信息:

  1. Data truncation: Out of range value for column 'vehicle_quality' at row 1这是核心错误,vehicle_quality列的插入值超出了其在数据库中定义的取值范围,MySQL 被迫截断数据但仍无法存储;
  2. Error updating database.:表示异常触发在数据库更新(此处为INSERT插入)阶段;
  3. The error occurred while setting parameters:参数绑定阶段发现值超出列范围,而非 SQL 语法错误;
  4. 涉及 SQL:向ddc_brand_models表插入数据时,vehicle_quality的参数值不符合列的定义约束。

简单来说:你要插入的vehicle_quality(车辆质量)数值,超过了数据库中该列设定的类型 / 长度上限,MySQL 拒绝存储并抛出数据截断异常

二、典型判断

看到该报错可立刻做出以下核心判断:

  1. 根因是「数据类型 / 范围不匹配」vehicle_quality列在数据库中的类型(如tinyint/smallint/int)的取值范围,远小于实际插入的数值;
  2. 非语法 / 连接问题:SQL 语句本身无语法错误,参数绑定也成功,只是数值超出列的物理约束;
  3. 错误与vehicle_quality列强相关:只需聚焦该列的数据库定义和插入值的匹配性,无需排查其他列;
  4. 可能的衍生问题:实体类中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 类型
tinyintByte/Integer
smallintShort/Integer
intInteger
bigintLong
decimalBigDecimal

示例:数据库列是DECIMAL(10,2),实体类字段应为BigDecimal

java

运行

private BigDecimal vehicleQuality;

五、避免方式(规范开发减少问题)

  1. 表结构设计时合理选择数据类型

    • 针对业务场景预估字段的取值范围,选择足够大但不冗余的类型(如车辆质量用int而非tinyint,金额用DECIMAL(10,2)而非float);
    • 对数值型字段明确单位(如千克 / 克),并在列注释中注明,避免单位混淆导致的范围错误。
  2. 实体类与数据库列类型严格匹配

    • 遵循「数据库类型→Java 类型」的映射规范,避免用Long接收数据库int列、用Integer接收decimal列;
    • 利用代码生成器(如 MyBatis Generator、若依代码生成器)自动生成实体类,减少手动映射错误。
  3. 业务层强制数据校验

    • 使用 Spring Validation(@Max/@Min/@DecimalMax等注解)或手动校验,对数值字段做范围限制;
    • 前端页面也需添加输入限制(如输入框最大值、正则校验),从源头拦截非法值。
  4. 开启 MySQL 严格模式my.cnf/my.ini中开启sql_mode=STRICT_TRANS_TABLES,让 MySQL 在数据截断时直接抛出异常(而非静默截断),便于开发阶段及时发现问题:

    ini

    [mysqld]
    sql_mode = STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION
    
  5. 测试覆盖边界值场景开发时对数值字段的最小值、最大值、临界值做测试(如车辆质量的 0、列上限值、超上限值),验证数据库和业务层的约束是否生效。

  6. 避免硬编码数值范围将数值范围配置在配置文件(如application.yml)中,便于后续调整:

    yaml

    business:
      vehicle:
        quality:
          min: 0
          max: 100000
    

    业务层读取配置做校验,避免硬编码导致的修改繁琐。

总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值