Spring Boot JPA读取Oracle数值字段自动追加.0问题求助
解决方案:根据Oracle存储值返回整数或小数
这个问题我之前处理过,核心原因是你用double类型定义实体字段——不管数据库里存的是整数还是小数,double都会把它解析成浮点数形式,整数自然就变成x.0了。而且涉及金额(比如保费TOTAL_PREMIUM),用double还存在精度丢失的风险,比如0.1+0.2的计算误差,这在财务场景里是绝对要避免的。
下面给你几个可行的解决方案,按推荐优先级排序:
1. 改用BigDecimal(最推荐)
用BigDecimal代替double是处理金额类字段的标准做法,它能精确表示数值,还能方便判断是否为整数。
步骤:
- 修改实体类字段定义:
import java.math.BigDecimal; import javax.persistence.Column; // ... 其他必要注解 @Column(name = "TOTAL_PREMIUM", precision = 12, scale = 2) private BigDecimal totalPremium = BigDecimal.ZERO;
- 自定义getter方法,根据数值类型返回对应结果:
public Number getFormattedTotalPremium() { // 去除末尾的0后,判断小数位是否为0 if (totalPremium.stripTrailingZeros().scale() <= 0) { // 是整数,返回Integer类型 return totalPremium.intValue(); } else { // 是小数,返回Double类型 return totalPremium.doubleValue(); } }
之后你就可以通过quotes.getFormattedTotalPremium()获取到符合要求的结果:存储整数时返回2、1348,存储小数时返回1389.48。
2. 不修改字段类型的临时方案(不推荐)
如果暂时不想改动字段类型,可以在原double字段的getter里做判断,但要注意double的精度风险:
public Number getTotalPremium() { // 判断当前值是否等于它的整数部分 if (totalPremium == Math.floor(totalPremium)) { return (int) totalPremium; } else { return totalPremium; } }
⚠️ 注意:这种方法在处理极大数时可能出现精度误差,比如非常大的整数可能因为浮点数的存储机制被近似表示,导致判断错误,所以仅适合临时应急。
3. 自定义JPA属性转换器
如果希望让JPA自动完成类型转换,可以实现AttributeConverter,让数据库的数值自动映射为Integer或Double:
第一步:创建转换器类
import java.math.BigDecimal; import javax.persistence.AttributeConverter; import javax.persistence.Converter; @Converter(autoApply = true) public class NumericToNumberConverter implements AttributeConverter<Number, BigDecimal> { @Override public BigDecimal convertToDatabaseColumn(Number attribute) { if (attribute == null) { return null; } // 将实体类的Number类型转成BigDecimal存储到数据库 return new BigDecimal(attribute.toString()); } @Override public Number convertToEntityAttribute(BigDecimal dbData) { if (dbData == null) { return null; } // 根据数据库值判断返回整数还是小数 if (dbData.stripTrailingZeros().scale() <= 0) { return dbData.intValue(); } else { return dbData.doubleValue(); } } }
第二步:修改实体类字段
@Column(name = "TOTAL_PREMIUM", precision = 12, scale = 2) @Convert(converter = NumericToNumberConverter.class) private Number totalPremium = 0;
这样查询时,JPA会自动把数据库的数值转换成对应的Integer或Double类型,直接调用quotes.getTotalPremium()就能得到想要的结果。
内容的提问来源于stack exchange,提问作者Awadesh
相关产品推荐
相关产品推荐

