谁动了我的代码——Long精度丢失
创始人
2025-07-08 19:30:37
0

一个诡异的现象

在进行数据结构设计时,我们通常需要考虑到相关业务的数据量等因素。比如非核心业务但数据量大并且频繁写入的表的主键,我们可能会考虑设计为Long类型。刚开始,数据量小,可能并不会发现什么问题。但是当数据量大了,或者Id采用雪花算法生成,这个时候诡异的事情便会发生。

后端数据正常返回,postman调试看数据也正常。但是当前端用后端返回的这个id查询相应的数据时,便会发生诡异的NotFoundException,或者查询的出来的数据和原先的数据不一致。

所以,谁偷偷动了我的代码?

JavaScript的数值精度

如果只从后端分析问题,或者只从前端分析问题,那永远也找不到答案。

在 JavaScript 中,数值类型默认会被转换为双精度浮点数,而双精度浮点数的精度有限,只能精确表示 2 的 53 次方以内(即 Number.MAX_SAFE_INTEGER,约为 9 x 10^15)的整数。对于超过该范围的长整数,JavaScript 会发生精度丢失,导致值变得不准确。

例如一个雪花算法生成的ID 1734042308679487490,前端获取到的值却变成了1734042308679487500

知道了问题的原因,问题就容易解决了——将Long类型作为String类型返回给前端即可。

一个简单的解决办法

(1) Spring Boot 中提供了 @JsonFormat 注解,可以对实体类中的属性进行序列化和反序列化格式化。对于 Long 类型的属性,可以设置其格式为字符串类型,并在前端进行相应的处理,以保持其精度不丢失。如:

public class Order {
  @JsonFormat(shape = JsonFormat.Shape.STRING)
  private Long id;
  ...
}

前端获取到的是string类型的数据,自然也不会有精度丢失的问题了。

(2) SpringBoot也支持在通过配置文件在项目级别,将数值类型的数据转成字符串返回给前端,通过在 application.properties 文件中添加配置即可:

# 默认为false
spring.jackson.seralization.WRITE_NUMBER_AS_STRINGS=true

(3) 如果不想使用 @JsonFormat 注解或者项目不是基于SpringBoot框架构建的,同样的思路,直接将Long类型转换成String返回给前端即可。

总结

在 JavaScript 中数值类型最大精度大约为9*10^15,即超过16位的数值一定会存在精度丢失问题。因此,后端返回Long类型的数值时,需要转换成String给到前端。

相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...
《非诚勿扰》红人闫凤娇被曝厕所... 【51CTO.com 综合消息360安全专家提醒说,“闫凤娇”、“非诚勿扰”已经被黑客盯上成为了“木...
2012年第四季度互联网状况报... [[71653]]  北京时间4月25日消息,据国外媒体报道,全球知名的云平台公司Akamai Te...