mybatis-plus IdWorker生成的Id和返回給前臺的不一致的解決

問題描述

今天在公司項目中修改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;
}
  1. @TableId(value = “id”, type = IdType.ID_WORKER)表示通過mybatis-plus自帶的優化版本的SnowFlake算法生成主鍵。
  2. 關於主鍵生成方式,可以看看這個類 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會自動給我們轉換。

到此這篇關於mybatis-plus IdWorker生成的Id和返回給前臺的不一致的解決的文章就介紹到這瞭,更多相關mybatis-plus IdWorker生成Id內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: