Mybatis-Plus自動(dòng)生成的數(shù)據(jù)庫id過長的解決
Mybatis-Plus自動(dòng)生成的數(shù)據(jù)庫id過長
一、問題
作為一名第一次使用mybatis-plus的萌新開發(fā)工程師,在項(xiàng)目開發(fā)過程中遇到一個(gè)問題。
當(dāng)使用mybatis-plus自帶的mybatis-generate生成DO文件,如下圖所示

DO類由注釋@Table修飾,主鍵id由注釋@Id,@GeneratedValue修飾。但是使用這樣的默認(rèn)DO進(jìn)行數(shù)據(jù)庫操作時(shí),會(huì)有導(dǎo)致數(shù)據(jù)庫自動(dòng)生成的主鍵id過長,如下所示

這樣的19位id,會(huì)存在一些問題:
1)前端拿到這樣的id后,會(huì)發(fā)生Number精度丟失,導(dǎo)致id數(shù)值發(fā)生變化,使得前后端的id不一致,這樣就使得無法利用id進(jìn)行操作
2)InnoDB存儲(chǔ)引擎的索引與記錄結(jié)構(gòu)是這樣的:
其索引與記錄的結(jié)構(gòu)是這樣的:

(1)主鍵索引與記錄存儲(chǔ)在一起;InnoDB通過主鍵索引查詢時(shí),能夠直接定位到行記錄。
(2)普通索引存儲(chǔ)主鍵(這下不是指針了);
這樣當(dāng)主鍵id是一個(gè)比較長的數(shù)值時(shí)每個(gè)索引都存儲(chǔ)這個(gè)值,在數(shù)據(jù)量大,內(nèi)存珍貴的情況下,MySQL有限的緩沖區(qū),存儲(chǔ)的索引與數(shù)據(jù)會(huì)減少,索引占用的磁盤空間也會(huì)增加,磁盤IO的概率會(huì)增加。
二、解決方案
通過詢問各位師兄和開發(fā)同學(xué),解決了這個(gè)問題,解決方案如下:

將DO類的注釋改為@TableName,主鍵id的注釋改為@TableId,這樣自動(dòng)生成的主鍵id就是正常位數(shù)。
至于為什么會(huì)這樣,我通過查閱資料得出一下結(jié)論
三、原理
1.首先了解下@GeneratedValue的使用。@GeneratedValue屬于JPA注解之一,JPA通過annotation來映射hibernate實(shí)體,基于annotation的hibernate主鍵標(biāo)識(shí)為@Id,其生成規(guī)則是由@GeneratedValue設(shè)定的。
JPA提供四種標(biāo)準(zhǔn)用法,由@GeneratedValue的源代碼可以明顯看出:
@Target({METHOD,FIELD})
@Retention(RUNTIME)
public @interface GeneratedValue{
GenerationType strategy() default AUTO;
String generator() default "";
}
其中GenerationType包含四種策略:
public enum GenerationType{
//使用一個(gè)特定的數(shù)據(jù)庫表格來保存主鍵。
TABLE,
//根據(jù)底層數(shù)據(jù)庫的序列來生成主鍵,條件是數(shù)據(jù)庫支持序列。
SEQUENCE,
//主鍵由數(shù)據(jù)庫自動(dòng)生成(主要是自動(dòng)增長型)
IDENTITY,
//主鍵由程序控制。
AUTO;
private GenerationType() {
}
}
其中的AUTO類型,在指定主鍵時(shí),如果不指定主鍵生成策略,默認(rèn)為AUTO。
即
@Id # 默認(rèn)生成策略為AUTO
效果等同于
@Id @GeneratedValue(strategy = GenerationType.AUTO)
由此可見,自動(dòng)生成的id和注解沒什么關(guān)系,那也許就是mybatis-plus的主鍵生成邏輯問題了。
通過去查詢mybatis-plus的文檔(文檔鏈接:https://baomidou.gitee.io/mybatis-plus-doc/#/spring-boot)

發(fā)現(xiàn)mybatis-plus默認(rèn)的主鍵生成是全局唯一的UUID,會(huì)導(dǎo)致生成的id過長。
并且官方也提供了解決方法,如下圖

可這只是將防止了前端接收時(shí)的精度丟失,并沒有解決我的問題。
根據(jù)文檔,可以得出一個(gè)新的解決辦法,并且不用更改DO類代碼:
將文檔中所說的id-type配置設(shè)置為0即可。
Mybatis-Plus id主鍵生成的問題
簡要說明
由于mybatis-plus會(huì)自動(dòng)插入一個(gè)id到實(shí)體對(duì)象, 不管你封裝與否, 所以有時(shí)候?qū)е乱恍┮馔獾那闆r發(fā)生
默認(rèn)是生成一個(gè)長數(shù)字字符串(編碼不同可能結(jié)尾帶有字母)
錯(cuò)誤
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
大致就是由于自動(dòng)生成了一個(gè)id1110423703487479810, 但是無法放入到integer中
解決方案一
1. 修改id字段類型
將id字段類型改為long, 這樣就能保證有足夠位數(shù)放入生成的id
2. 調(diào)整數(shù)據(jù)庫id字段類型
將數(shù)據(jù)庫的id字段的長度(改為20位)
解決方案二
如果想要使用id自增的, 就需要把mybatis-plus這個(gè)id生成的功能給關(guān)掉
添加注解
在id字段上加上如下注解即可
@TableId(value = "id",type = IdType.AUTO)
其他type類型介紹
AUTO:AUTO(0, “數(shù)據(jù)庫ID自增”),INPUT:INPUT(1, “用戶輸入ID”),ID_WORKER:ID_WORKER(2, “全局唯一ID”),UUID:UUID(3, “全局唯一ID”),NONE:NONE(4, “該類型為未設(shè)置主鍵類型”),ID_WORKER_STR:ID_WORKER_STR(5, “字符串全局唯一ID”);
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot整合Mybatis使用Druid數(shù)據(jù)庫連接池
這篇文章主要介紹了SpringBoot整合Mybatis使用Druid數(shù)據(jù)庫連接池,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03
java實(shí)現(xiàn)微信掃碼登錄第三方網(wǎng)站功能(原理和代碼)
為避免繁瑣的注冊(cè)登陸,很多平臺(tái)和網(wǎng)站都會(huì)實(shí)現(xiàn)三方登陸的功能,增強(qiáng)用戶的粘性。這篇文章主要介紹了java實(shí)現(xiàn)微信掃碼登錄第三方網(wǎng)站功能(原理和代碼),避免做微信登錄開發(fā)的朋友們少走彎路2022-12-12
基于SpringBoot和Vue實(shí)現(xiàn)分片上傳系統(tǒng)
最近想做一個(gè)關(guān)于文件上傳的個(gè)人小網(wǎng)盤,一開始嘗試使用了OSS的方案,但是該方案對(duì)于大文件來說并不友好,所以開始嘗試分片上傳方案的探索,接下來小編給大家詳細(xì)的介紹一下如何基于SpringBoot和Vue實(shí)現(xiàn)分片上傳系統(tǒng),需要的朋友可以參考下2023-12-12
優(yōu)化SpringBoot程序啟動(dòng)速度的實(shí)現(xiàn)
本文主要介紹了優(yōu)化SpringBoot程序啟動(dòng)速度的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01
詳解Spring Batch 輕量級(jí)批處理框架實(shí)踐
這篇文章主要介紹了詳解Spring Batch 輕量級(jí)批處理框架實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06

