爲什麼要取這個標題呢?因爲如果情況和我遇到的一樣,也不知道原因就會這麼搜,比如我。?
問題描述
今天在公司項目中修改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
會自動給我們轉換。