为什么要取这个标题呢?因为如果情况和我遇到的一样,也不知道原因就会这么搜,比如我。?
问题描述
今天在公司项目中修改id的生成策略为mybatis-plus
自带的IdWorker
策略时,发现返回给前台的id竟然和数据库不一致。费解得很呐。
package net.mshome.twisted.tmall.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 数据库实体类的父类,必需字段
*
* @author [email protected]
* @date 2019/9/6
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class BaseEntity implements Serializable {
private static final long serialVersionUID = 236424297319280526L;
/**
* 数据表主键,此处采用mybatis-plus自带的IdType.ID_WORKER策略
*/
@TableId(value = "id", type = IdType.ID_WORKER)
protected Long id;
/**
* 数据创建时间
*/
@TableField(fill = FieldFill.INSERT)
protected LocalDateTime createTime;
/**
* 数据更新时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
protected LocalDateTime updateTime;
}
@TableId(value = "id", type = IdType.ID_WORKER)
表示通过mybatis-plus
自带的优化版本的SnowFlake算法生成主键。- 关于主键生成方式,可以看看这个类
com.baomidou.mybatisplus.core.toolkit.IdWorker
问题原因
mybatis-plus
的ID_WORKER
策略会生成一个Long
型的很长长长长的数字,这个数字传到前台之后,超过了js
中数字的最大范围,具体表现为最后两位始终为 0。
解决办法
很容易想到,超过了js
数字最大范围,那直接转成String
类型就完了。
方案一(适合BaseEntity方式)
package net.mshome.twisted.tmall.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 数据库实体类的父类,必需字段
*
* @author [email protected]
* @date 2019/9/6
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class BaseEntity implements Serializable {
private static final long serialVersionUID = 236424297319280522L;
/**
* 数据表主键
*/
@TableId(value = "id", type = IdType.ID_WORKER)
@JsonSerialize(using = ToStringSerializer.class)
protected Long id;
/**
* 数据创建时间
*/
@TableField(fill = FieldFill.INSERT)
protected LocalDateTime createTime;
/**
* 数据更新时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
protected LocalDateTime updateTime;
}
- 添加
@JsonSerialize(using = ToStringSerializer.class)
将结果转换成String
。- 此方案适合有
baseEntity
的时候,避免每个entity
都要单独维护,很麻烦。
方案二(全局处理-两种方式)
package net.mshome.twisted.tmall.configuration;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
* 系统通用简单配置
*
* @author [email protected]
* @date 2019/10/16
*/
@Configuration
public class TmallConfiguration {
/**
* 方式一:此方式可以灵活配置任意类型的序列化反序列化
*/
@Bean
public Jackson2ObjectMapperBuilderCustomizer builderCustomizer() {
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
DateTimeFormatter dateTimeSerializeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
DateTimeFormatter dateTimeDeserializeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
return builder -> {
// 所有Long类型转换成String到前台
builder.serializerByType(Long.class, ToStringSerializer.instance);
builder.serializerByType(LocalDate.class, new LocalDateSerializer(dateFormatter));
builder.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(dateTimeSerializeFormatter));
builder.deserializerByType(LocalDateTime.class, new LocalDateTimeDeserializer(dateTimeDeserializeFormatter));
};
}
/**
*
* 方式二:采用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);
simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
objectMapper.registerModule(simpleModule);
return objectMapper;
}
}
直接将所有的
Long
类型转换为String
给前台展示。后台用Long
接收前台传入的数字String
也可以的,Spring
会自动给我们转换。