1、场景介绍
项目场景:目前市场上的大多数项目对于对象表建设的ID属性使用的是Long性并使用雪花算法生成,少量使用String的UUID,极少量的使用Long类型的自增长。
1.1 . Long型雪花算法ID
雪花算法 : 分布式id生成算法的有很多种,Twitter的SnowFlake就是其中经典的一种。
- 优点:雪花算法id是一个64bits的Long数据,第一位为零表示其为正数,最后12位为其序列号,生成的id既能完美契合分布式ID的需求,同时后12位序列号也能够保证主键的有序性。
- 缺点:雪花算法的长度是19(long型最多19位)位的,前端能够接收的数字最多只能是16位的,因此就会造成精度丢失,导致相关业务无法处理。
1.2 UUID
UUID : 是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的。在UUID的算法中,可能会用到诸如网卡MAC地址,IP,主机名,进程ID等信息以保证其独立性。
- 优点:UUID不是通过数据库的主键生成器生成的,在入库之前就能够获取到其主键,非常符合分布式主键的设计。
- 缺点:UUID没有规律可循,无法保证主键的插入顺序型。且UUID在意外情况下(mac地址等其他生成UUID的因素相同的情况)可能会出现UUID相同。
1.3 自增Long型主键
- 优点:自增主键保证了,插入数据的主键永远比已有的数据的主键大。(看不懂就去复习数据结构)
- 缺点:需要等待插入完成才有主键,或者等待主键生成器返回才会有主键。不利于分布式的设计。
2、问题描述:
某次开发时前端直接给俺说ID传递到前端是失真了,俺一看果真如此,反应过来是ID过长导致失真,做个记录让遇到类似问题的小伙伴能够快速的解决。
错误如下:
3、原因分析
雪花算法生成的分布式ID长度为19位,前端JS接收数字能够达到的最大精度为16位,因此导致前端得到的ID不是真正的ID,导致后续操作无法进行。
4、解决方案
4.1 方案一
在相关需要转换的ID上加注解完成转换(需要在每一个res中的ID上加)
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
@Data
public class BusinessTreeRes {
/**
* 方式一:JsonSerialize注解
* 主键
*/
@JsonSerialize(using = ToStringSerializer.class)
private Long typeId;
}
4.2 在拦截器中加Long型数据转换方法(推荐使用)
@Configuration
@EnableWebMvc
public class InterceptorConfig implements WebMvcConfigurer {
/**
* 方式二:拦截器转换
* web层统一处理Long转String问题
* @param converters 需要转换的对象
*/
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper objectMapper = jackson2HttpMessageConverter.getObjectMapper();
SimpleModule simpleModule = new SimpleModule();
//将Long转为string 解决id过大 js显示问题
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
objectMapper.registerModule(simpleModule);
jackson2HttpMessageConverter.setObjectMapper(objectMapper);
converters.add(0, jackson2HttpMessageConverter);
}
}
4.3 自定义配置类
/**
* 类型转换配置
*
* @author xiefei15
* @version 1.0
* @date 2020/6/5 15:20
*/
@Configuration
public class DataTypeConvertConfig{
/**
*
* 方式三:采用objectMapper注入
*/
@Bean
public ObjectMapper objectMapper (Jackson2ObjectMapperBuilder builder) {
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
SimpleModule simpleModule = new SimpleModule();
// 直接将所有的Long类型转换为String
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
objectMapper.registerModule(simpleModule);
return objectMapper;
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/117241.html