Java中存储千克单位数据的最优数据类型如何选择
该场景最优实现方案说明
首先纠正认知误区
BigDecimal不存在「只能保留小数点后两位」的限制,它支持自定义精度、小数位数和舍入规则,完全可以满足千克计量的需求。
不推荐使用Double的原因
Double是二进制浮点类型,无法精确表示大部分十进制小数,比如0.1的二进制存储本身就是近似值,多次累加、乘除运算后会产生不可控的精度误差,完全不适合计量、交易类对精度要求高的场景。
可选方案(按优先级排序)
方案1:使用BigDecimal(优先推荐)
适配性最高,适合需要灵活调整小数精度、有复杂计量运算的场景,配置方式如下:
- 实体类字段修改
@Entity @Table(name="raw_material_harvest_projection", schema = "dbo") @Data @Builder @AllArgsConstructor @NoArgsConstructor public class RawMaterialHarvestProjection { @Id @Column(name = "id") @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @NotNull @ManyToOne @JoinColumn(name = "raw_material") private RawMaterial rawMaterial; @NotNull // precision是数字总位数,scale是小数位数,以下配置支持最大999999.999千克(精确到0.001千克即1克),可按需调整 @Column(name = "quantity", precision = 9, scale = 3) private BigDecimal quantity; }
- 运算注意事项
- 所有运算直接调用BigDecimal的
add()、subtract()、multiply()、divide()方法,不要转成Double运算 - 涉及除不尽的场景提前指定舍入规则,比如四舍五入用
RoundingMode.HALF_UP - 初始化时尽量用字符串构造,比如
new BigDecimal("0.1"),不要用new BigDecimal(0.1)避免带入浮点误差
方案2:用Long存储最小计量单位
如果你的业务场景精度固定,比如最高只需要精确到克(0.001kg)或者毫克(0.000001kg),可以直接用Long类型存储最小单位的整数数值,完全避免精度问题,性能也更高:
@NotNull @Column(name = "quantity_gram") private Long quantityGram; // 存储单位为克,1kg=1000g // 业务层提供转换为千克的方法 public BigDecimal getQuantityInKg() { return BigDecimal.valueOf(quantityGram).divide(BigDecimal.valueOf(1000), 3, RoundingMode.HALF_UP); }
选型建议
- 如果需要灵活调整精度、有复杂的单位换算需求,选BigDecimal
- 如果精度固定、追求极致性能、不想处理BigDecimal的舍入规则,选Long存最小单位
内容的提问来源于stack exchange,提问作者Vitor
相关产品推荐
相关产品推荐

