案例场景
项目使用的是雪花算法生成的主键id(19位)长整型的,在前端调用接口之后发现返回结果id被裁减了(精度缺少)。经过组内同事定位📌Long型精度损失。具体原因下面原理部分分析。
雪花(snowflake)Id,Long id前端精度损失原因
本人试验以及结合网上的文章,发现一个问题,在PostMan里面请求接口能够完全正确的返回雪花算法生成的主键id,但是在Swagger或者前端接口请求 浏览器之中就会出现雪花算法精度损失问题。于是查找原因如下:
JavaScript 不支持后台返回的 Long 类型,JavaScript 的 number 类型的数值范围是 -2^53~2^53(不包含边界) 所以大于 9007199254740991 的数,进制转换会存在精度问题,而雪花ID生成的数值过大,导致 JavaScript 不能正常存储导致。
代码解读复制代码 同时注意:建议雪花ID在数据库中使用 bigint 来存储,而不是使用 varchar;这样可以提高这样数据库的速度,使用索引的时候少一步字符串转换成数字的操作。
于是我的实际项目之中返回的雪花算法的主键id
JavaScript的Number最大id 9007199254740991 16位
项目主键id 1511972392982179840 19位
浏览器或者swagger返回 1511972392982179800
于是就出现了 前端传递的id,找寻不到对应的记录问题。
解决JavaScript Number长整型精度丢失问题
后端
解决方案1
@JSONField(serializeUsing= ToStringSerializer.class) 这个注解是Fastjson的,旨在让系统系列化时,保留相关精度。 `
在VO类中,id上添加注释
@Configuration
public class JacksonConfig {
@Bean
@Primary
@ConditionalOnMissingBean(ObjectMapper.class)
public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder)
{
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
// 全局配置序列化返回 JSON 处理
SimpleModule simpleModule = new SimpleModule();
//JSON Long ==> String
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
objectMapper.registerModule(simpleModule);
return objectMapper;
}
}
前端
待补充 ~~