在一次业务中,由于我们的主键ID生成策略是IdType.ID_WORKER(MyBatis-Plus中自带的生成策略),所以在数据库中生成了例如1564500252138758146的19位主键,且实体类是用Long类型来接收的,且返回给前端的类型是List< Long >类型,最后造成了精度损失的问题,前端接收到数据与后端的数据不一致。
点进IdType里面,我们可以看到
/**
*
* 生成ID类型枚举类
*
*
* @author hubin
* @since 2015-11-10
*/
@Getter
public enum IdType {
/**
* 数据库ID自增
*/
AUTO(0),
/**
* 该类型为未设置主键类型
*/
NONE(1),
/**
* 用户输入ID
* 该类型可以通过自己注册自动填充插件进行填充
*/
INPUT(2),
/* 以下3种类型、只有当插入对象ID 为空,才自动填充。 */
/**
* 全局唯一ID (idWorker)
*/
ID_WORKER(3),
/**
* 全局唯一ID (UUID)
*/
UUID(4),
/**
* 字符串全局唯一ID (idWorker 的字符串表示)
*/
ID_WORKER_STR(5);
private final int key;
IdType(int key) {
this.key = key;
}
}
MP支持以下4种主键策略
值 | 描述 |
---|---|
IdType.AUTO | 数据库ID自增 |
IdType.INPUT | 用户输入ID |
IdType.ID_WORKER | 全局唯一ID,内容为空自动填充 |
IdType.UUID | 全局唯一ID,内容为空自动填充 |
对于Long类型的数据,如果我们在Controller层将结果序列化json,直接传给前端的话,在Long类型数据长度大于17位时会出现精度损失的问题。在Java中long数据类型是64位,最大值是2^63
-1,然后JavaScript中的number类型,最大的安全整数2^53-1。因此,对于Long类型,后端需要转换为字符串传给前端才不会出现按精度损失的问题。
根据网上的案例,对于在序列化时需要保留精度的字段,添加@JsonSerialize注解即可
@JsonSerialize(using = ToStringSerializer.class)
private List<Long> id;
但是,经由实践,不知道为什么,我在自己的swagger上测试以及在postman上测试,精度都没有损失,但是实际到了前端,就出现了精度损失的情况,后来,我发现,swagger上以及postman上精度没损失,但是到了redis缓存中就出现了精度损失的问题。不知道是什么原因,有哪位大佬能否解答以下
使用方案一不能解决这个问题之后,最终还是还是将dto中要保留精度的字段改成了String类型,然后将Long类型转换为String返回给前端,这样才得以解决