You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot 2.7.1升级后DataJpaTest中NUMERIC默认精度异常问题

Spring Boot 2.7.1升级后H2模拟PostgreSQL时NUMERIC数据截断问题

问题场景

使用@DataJpaTest,通过schema.sql和data.sql搭建基于H2模拟PostgreSQL的测试环境。将spring-boot-starter-parent从2.6.3升级到2.7.1后,测试出现断言失败:

org.opentest4j.AssertionFailedError: 
Expected :1.4321
Actual   :1

查看H2数据库发现,problematic_number字段存储的值为1而非插入的1.4321,升级前测试完全正常。将schema.sql中字段定义改为NUMERIC(10,4)后测试恢复正常。

相关代码

schema.sql:

CREATE TABLE IF NOT EXISTS some_table(
    id BIGSERIAL,
    name TEXT,
    problematic_number NUMERIC NOT NULL
);

data.sql:

INSERT INTO some_table (name, problematic_number) VALUES ('something', 1.4321);

原因分析

核心原因是Spring Boot 2.7.x升级了依赖的H2数据库版本(从2.0.x系列升级到2.1.x+),H2在PostgreSQL兼容模式下对无参数NUMERIC类型的默认处理逻辑发生了变更:

  • Spring Boot 2.6.x配套的H2版本中,无参数NUMERIC默认会保留输入的小数部分,行为接近PostgreSQL原生(PostgreSQL中NUMERIC默认精度无限制,会保留输入的所有小数位)。
  • 升级后的H2版本在PostgreSQL模式下,将无参数NUMERIC默认映射为NUMERIC(18,0),即默认小数位为0,导致插入的小数被直接截断为整数。

解决方案

有两种可行的处理方式:

1. 显式指定NUMERIC的精度和小数位

直接在表结构定义中明确NUMERIC的精度和小数位,确保行为一致:

CREATE TABLE IF NOT EXISTS some_table(
    id BIGSERIAL,
    name TEXT,
    problematic_number NUMERIC(10,4) NOT NULL
);

这种方式最直接,也能避免依赖数据库的默认行为,保证表结构定义的明确性。

2. 调整H2配置参数

在测试环境的H2连接URL中指定默认的NUMERIC精度和小数位,比如在application-test.properties中配置:

spring.datasource.url=jdbc:h2:mem:testdb;MODE=PostgreSQL;DEFAULT_NUMERIC_PRECISION=10;DEFAULT_NUMERIC_SCALE=4;DB_CLOSE_DELAY=-1

通过DEFAULT_NUMERIC_PRECISION和DEFAULT_NUMERIC_SCALE参数,强制H2在PostgreSQL模式下使用自定义的默认精度,匹配升级前的行为。

内容的提问来源于stack exchange,提问作者Sebastian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 17:01:37