简要说明
由于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 * <p>该类型可以通过自己注册自动填充插件进行填充,不设置的话默认是雪花算法</p> */ 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前添加星号可以使项目热加载成功<br> # 自定义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
雪花算法介绍
譬如当前的环境建设的内容是:四个环境处于四个不同的子网(dev、test、stg、prod),其中四个子网中的主机号最长的是16位,所以得到了下面的针对于AO部门所有pod的雪花ID结构
定长的思考
首先雪花算法本身是不能够保证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