• 数字精度问题


    问题描述

    今天在修改一个系统日志功能时,发现我接口返回给前端的数据中出现了重复的日志ID:

    重复ID
    后端使用 spring-data-mongodb 将日志数据保存到 mongodb 中,日志记录的ID采用 java.lang.Long 类型定义,保存日志是通过 Snowflake 算法生成的全局唯一ID;

    在这里插入图片描述


    原因分析:

    首先怀疑是数据库保存数据问题,先通过重复的日志ID到数据库查询日志信息:
    在这里插入图片描述
    这里查询出来的ID居然不一样,懵逼…, 再修改一下ID,还是查出来同一条记录:
    在这里插入图片描述在这里插入图片描述
    明明ID不一样但是的确能查询出来,后三位数字无论怎么修改查询结果都不影响,想不通…,然后我开始怀疑是不是ID不能用java.lang.Long 类型,后来通过单元测试模拟了一条日志保存和查询,居然没有问题,ID 保存到 mongodb 前的值和查询出来的值是一致的。
    再次查看接口的返回数据(响应栏),ID并没有重复,但是通过预览栏查看为什么是重复的呢?突然想到好像JS中的数子是Number类型,使用IEEE754格式来表示整数和浮点值,这里的ID为19位数字,应该是丢失了精度。
    在这里插入图片描述
    既然前端JS不支持Long类型数字,那就将Long转换为String返回给前段,只需要在Id属性上添加 @JsonFormat(shape = JsonFormat.Shape.STRING) 注解就OK啦
    在这里插入图片描述

    再来看看mongodb根据ID查询的问题:mongodb中默认数字类型也是浮点数类型,所有上面我们的查询中的查询条件 1552841301425262600 丢失精度后为 1552841301425262590,mongodb 在执行查询过程中应该会把数据库中的ID属性转换为和查询条件相同的数据类型,而数据库中的记录ID 1552841301425262593 丢失精度后也为 1552841301425262590,所以能查询出来,
    在这里插入图片描述
    正确的查询条件应该为:NumberLong(“1552841301425262592”)
    在这里插入图片描述
    在这里插入图片描述


    终结:

    • 前端JS不支持Long类型数字,返回给前端Long类型数据时需要转换为String
    • mongodb中默认数字类型也是浮点数类型,在查询数据时要注意属性类型
  • 相关阅读:
    网络安全 day6 --- 抓包技术&HTTPS协议&小程序&PC应用&WEB&转发联动
    vue2使用change事件监听不了回车事件的问题
    国内镜像源网址
    【网络安全 --- Burp Suite抓包工具】学网安必不可少的Burp Suite工具的安装及配置
    【--知识点整理--】
    什么是NoSQL?什么是redis?redis是做什么的?
    2022 万向区块链秋季黑客马拉松全球报名开启!
    一个Adapter+recycleview实现多种布局,区分布局中
    Linux IO多路复用模型
    SpringBoot分布式框架
  • 原文地址:https://blog.csdn.net/i_love_t/article/details/126371430