基于雪花算法解决Mybatis-Plus id主键生成的问题

目录

简要说明

错误

解决方案一

1. 修改id字段类型

2. 调整数据库id字段类型

解决方案二

添加注解

定长的思考

参考文章


简要说明

由于mybatis-plus会自动插入一个id到实体对象, 不管你封装与否, 所以有时候导致一些意外的情况发生

默认是生成一个长数字字符串(编码不同可能结尾带有字母)

错误

ested exception is org.apache.ibatis.reflection.ReflectionException: Could not set property 'id' of 'class com.xxx' with value '1110423703487479810' Cause: java.lang.IllegalArgumentException: java.lang.ClassCastException@14041406

大致就是由于自动生成了一个id1110423703487479810, 但是无法放入到integer

解决方案一

1. 修改id字段类型

将id字段类型改为long, 这样就能保证有足够位数放入生成的id

2. 调整数据库id字段类型

将数据库的id字段的长度(改为20位)

解决方案二

如果想要使用id自增的, 就需要把mybatis-plus这个id生成的功能给关掉

添加注解

id字段上加上如下注解即可

 @TableId(value = "id",type = IdType.AUTO)

Mybatis plus3.3.0的IdType介绍

package com.baomidou.mybatisplus.annotation;

import lombok.Getter;

/**
 * 生成ID类型枚举类
 *
 * @author hubin
 * @since 2015-11-10
 */
@Getter
public enum IdType {
    /**
     * 数据库ID自增
     */
    AUTO(0),
    /**
     * 该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)
     */
    NONE(1),
    /**
     * 用户输入ID
     * 

该类型可以通过自己注册自动填充插件进行填充,不设置的话默认是雪花算法

*/ INPUT(2), /* 以下3种类型、只有当插入对象ID 为空,才自动填充。 */ /** * 分配ID (主键类型为number或string) * * @since 3.3.0 */ ASSIGN_ID(3), /** * 分配UUID (主键类型为 string) */ ASSIGN_UUID(4), /** * @deprecated 3.3.0 please use {@link #ASSIGN_ID} */ @Deprecated ID_WORKER(3), /** * @deprecated 3.3.0 please use {@link #ASSIGN_ID} */ @Deprecated ID_WORKER_STR(3), /** * @deprecated 3.3.0 please use {@link #ASSIGN_UUID} */ @Deprecated UUID(4); private final int key; IdType(int key) { this.key = key; } }

雪花算法类com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator

雪花算法xml配置写法如下

mybatis-plus:
  #mapper-locations: classpath:mybatis/**/*Mapper.xml
  # 在classpath前添加星号可以使项目热加载成功
# 自定义xml sql文件需要配置这个 mapper-locations: classpath*:mybatis/**/*Mapper.xml #实体扫描,多个package用逗号或者分号分隔 typeAliasesPackage: com.nis.project global-config: #主键类型 0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"全局唯一ID UUID"; id-type: 3 #机器 ID 部分(影响雪花ID) workerId: 1 #数据标识 ID 部分(影响雪花ID)(workerId 和 datacenterId 一起配置才能重新初始化 Sequence) datacenterId: 18 #字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断" field-strategy: 2 #驼峰下划线转换 db-column-underline: true #刷新mapper 调试神器 refresh-mapper: true #数据库大写下划线转换 #capital-mode: true #序列接口实现类配置 #key-generator: com.baomidou.springboot.xxx #逻辑删除配置(下面3个配置) logic-delete-value: 0 logic-not-delete-value: 1 #自定义SQL注入器 #sql-injector: com.baomidou.mybatisplus.mapper.LogicSqlInjector #自定义填充策略接口实现 #meta-object-handler: com.baomidou.springboot.xxx configuration: map-underscore-to-camel-case: true cache-enabled: false # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

雪花算法介绍 

基于雪花算法解决Mybatis-Plus id主键生成的问题_第1张图片 譬如当前的环境建设的内容是:四个环境处于四个不同的子网(dev、test、stg、prod),其中四个子网中的主机号最长的是16位,所以得到了下面的针对于AO部门所有pod的雪花ID结构

  基于雪花算法解决Mybatis-Plus id主键生成的问题_第2张图片

定长的思考

首先雪花算法本身是不能够保证ID定长的,所以要想达到定长的效果,需要额外处理一下。针对于要求定长18的场景。其最大id为:999999999999999999L,最小id为:100000000000000000L。

针对一个定长的id其能够支持的年数如下(另id最大值为maxId,最小值为minId,时间戳的偏移量为timestampShift,一年的秒数为yearSec):

yearNum = ((maxId >> timestampShift) - (minId >> timestampShift)) / yearSec

可以通过制定一个时间作为雪花id的开始时间,另当前时间和开始时间差值所产生的id为最小id即可保证id的最小值为指定长度,同时通过上面的公式可以计算出多少年之后产生的id不会超过固定位数。

  

参考文章

mybatis-plus id主键生成的坑___WanG的博客-CSDN博客_mybatisplus 自增id

你可能感兴趣的:(框架,java,雪花算法,mybatis-plus)