mybatisplus使用雪花id通过swagger返回ID时精度丢失问题

xml 复制代码
在使用mybatisplus自带雪花的时候会发现返回的ID是19位的长度,因此在通过swagger页面展示的时候会发现后端返回的和页面展示的ID不一致问题。是因为精度丢失的问题。因此需要更改雪花ID的长度


xml 复制代码
跟踪进去:


发现是DefaultIdentifierGenerator类实现了IdentifierGenerator并重写了nextId方法,因此需要我们重写nextId方法

  • 进行重写:
java 复制代码
package com.ssdl.config.automatic;

import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import com.ssdl.util.IdGenerator;
import org.springframework.stereotype.Component;

@Component
public class CustomerIdGenerator implements IdentifierGenerator {
    @Override
    public Number nextId(Object entity) {
        return IdGenerator.generateId();
    }
}
java 复制代码
package com.ssdl.util;

import java.util.Date;
import java.util.UUID;
 
/**
 * compressed id generator, result id not great than 53bits before 2318-06-04.
 */
public class IdGenerator {
 
    private static IdGenerator instance = new IdGenerator(0);
 
    public static IdGenerator initDefaultInstance(int machineId) {
        instance = new IdGenerator(machineId);
        return instance;
    }
 
    public static IdGenerator getInstance() {
        return instance;
    }
 
    public static long generateId() {
        return instance.nextId();
    }
 
    // total bits=53(max 2^53-1:9007199254740992-1)
 
    // private final static long TIME_BIT = 40; // max: 2318-06-04
    private final static long MACHINE_BIT = 5; // max 31
    private final static long SEQUENCE_BIT = 8; // 256/10ms
 
    /**
     * mask/max value
     */
    private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT);
    private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);
 
    private final static long MACHINE_LEFT = SEQUENCE_BIT;
    private final static long TIMESTMP_LEFT = MACHINE_BIT + SEQUENCE_BIT;
 
    private long machineId;
    private long sequence = 0L;
    private long lastStmp = -1L;
 
    private IdGenerator(long machineId) {
        if (machineId > MAX_MACHINE_NUM || machineId < 0) {
            throw new IllegalArgumentException(
                    "machineId can't be greater than " + MAX_MACHINE_NUM + " or less than 0");
        }
        this.machineId = machineId;
    }
 
    /**
     * generate new ID
     *
     * @return
     */
    public synchronized long nextId() {
        long currStmp = getTimestamp();
        if (currStmp < lastStmp) {
            throw new RuntimeException("Clock moved backwards.  Refusing to generate id");
        }
 
        if (currStmp == lastStmp) {
            sequence = (sequence + 1) & MAX_SEQUENCE;
            if (sequence == 0L) {
                currStmp = getNextTimestamp();
            }
        } else {
            sequence = 0L;
        }
 
        lastStmp = currStmp;
 
        return currStmp << TIMESTMP_LEFT //
                | machineId << MACHINE_LEFT //
                | sequence;
    }
 
    private long getNextTimestamp() {
        long mill = getTimestamp();
        while (mill <= lastStmp) {
            mill = getTimestamp();
        }
        return mill;
    }
 
    private long getTimestamp() {
        // per 10ms
        return System.currentTimeMillis() / 10;// 10ms
    }
 
    public static Date parseIdTimestamp(long id) {
        return new Date((id >>> TIMESTMP_LEFT) * 10);
    }
 
    public static String uuid() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }
}

插曲:

在使用mybatisplus时自动插入创建时间之类的操作:

java 复制代码
package com.ssdl.config.autoMatic;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
public class MybatisHandler implements MetaObjectHandler {
	@Override
	public void insertFill(MetaObject metaObject) {
		//属性名
		this.setFieldValByName("createTime", new Date(), metaObject);
		this.setFieldValByName("updateTime", new Date(), metaObject);
		this.setFieldValByName("isDel", 0, metaObject);
		this.setFieldValByName("createUser", "admin", metaObject);
		this.setFieldValByName("updateUser", "admin", metaObject);
		//this.setFieldValByName("createUser", SecureUtil.getUserId(), metaObject);
        //不维护create_user可以不使用这行代码
	}
 
	@Override
	public void updateFill(MetaObject metaObject) {
		//属性名
		this.setFieldValByName("updateTime", new Date(), metaObject);
		this.setFieldValByName("updateUser", "admin", metaObject);
		//this.setFieldValByName("updateUser", SecureUtil.getUserId(), metaObject);
	}
}
java 复制代码
	@TableId(value = "id",type = IdType.ASSIGN_ID)
    private Long id;

    /**
     * 进行新增或者更新操作时
     * Mybatis自动进行维护时间
     */
    @TableField(fill= FieldFill.INSERT)
    private String createUser;

    @TableField(fill=FieldFill.INSERT)
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date createTime;

    @TableField(fill=FieldFill.INSERT_UPDATE)
    @JsonIgnore
    private String updateUser;

    @TableField(fill= INSERT_UPDATE)
    @JsonIgnore
    private Date updateTime;

    @TableLogic
    @TableField(fill= FieldFill.INSERT)
    @JsonIgnore
    private Integer isDel;
相关推荐
都叫我大帅哥1 小时前
深入浅出 Resilience4j:Java 微服务的“免疫系统”实战指南
java·spring cloud
Cao_Shixin攻城狮3 小时前
Flutter运行Android项目时显示java版本不兼容(Unsupported class file major version 65)的处理
android·java·flutter
Dcs6 小时前
还在用 Arrays.hashCode?Java 自己也能写出更快的版本!
java
fouryears_234178 小时前
Spring,Spring Boot 和 Spring MVC 的关系以及区别
java·spring boot·spring·mvc
阿葱(聪)8 小时前
java 在k8s中的部署流程
java·开发语言·docker·kubernetes
浮生带你学Java9 小时前
2025Java面试题及答案整理( 2025年 7 月最新版,持续更新)
java·开发语言·数据库·面试·职场和发展
板板正9 小时前
SpringAI——提示词(Prompt)、提示词模板(PromptTemplate)
java·spring boot·ai·prompt
板板正9 小时前
SpringAI——对话记忆
java·spring boot·ai
期待のcode9 小时前
图片上传实现
java·前端·javascript·数据库·servlet·交互
李长渊哦9 小时前
深入理解Java中的Map.Entry接口
java·开发语言