数据库金额用Decimal还是BigInt来表示


💰 金额字段设计与 BigDecimal 笔记


一、为什么不能用 float/double 表示金额?

  • float / double 属于 二进制浮点数,底层无法精确表示大多数十进制小数。

  • 示例:

    System.out.println(0.1 + 0.2);  // 输出:0.30000000000000004
    
  • 会导致 金额误差,在金融、电商等系统中无法接受。


二、BigDecimal 是怎么解决精度问题的?

  • BigDecimal 使用 定点数表示法

    • unscaledValue: 实际整数值

    • scale: 小数位数

  • 例如:

    BigDecimal amount = new BigDecimal("123.45");
    // 实际底层等价于 unscaledValue = 12345, scale = 2
    

✅ 这样就能精确表示任意小数,避免了浮点误差。


三、数据库中金额字段怎么选?

方案一:使用 DECIMAL(p, s) 类型(推荐)

  • 精确表示小数,如 DECIMAL(18,2) 表示最多 18 位,其中 2 位为小数。

  • 自动映射为 Java 的 BigDecimal,无精度丢失。

✔ 优点:

  • 精确、安全

  • 代码和 SQL 表达一致,易读、易维护

  • 支持 SQL 的金额聚合、计算函数

✘ 缺点:

  • 存储空间稍大

  • 极少数情况下性能略低于整型


方案二:金额转整数,用 BIGINT 存储(高性能方案)

  • 将金额 *100(即“元转分”)存为整数,显示时再除以 100。

  • Java 使用 long 存储,如 12345 表示 123.45 元

✔ 优点:

  • 存储空间小,查询快

  • 可在极限高并发下优化性能

✘ 缺点:

  • 不直观,容易混淆单位(分/厘/毫)

  • 所有金额字段都需特殊转换

  • 数据库聚合计算易错


四、Java 金额字段应该用什么类型?

类型是否推荐原因说明
float / double❌ 不推荐有精度误差
BigDecimal✅ 推荐精确,适合金额计算
long✔ 特殊场景可用于“金额转分”场景

五、最佳实践总结 ✅

场景类型说明
数据库金额字段DECIMAL(18,2)业务直观、安全精确,主流做法
Java 金额变量BigDecimal避免浮点误差,直接与 DB 对应
极限性能、明确单位规范场景BIGINT金额转分存储,但需全局规范配套

🔚 结语

  • 对于绝大多数应用,数据库用 DECIMAL,Java 用 BigDecimal 是首选方案

  • 使用整型模拟金额需要配套好单位约定、工具类支持,并且团队成员都理解。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值