# 怎么解決Mybatis-Plus自動生成的數據庫id過長問題
## 引言
在使用Mybatis-Plus進行開發時,很多開發者會遇到自動生成的數據庫主鍵ID過長的問題。默認情況下,Mybatis-Plus采用雪花算法(Snowflake)生成分布式ID,這種ID通常是一個18-19位的長整型數字。雖然這種ID在分布式系統中具有很好的唯一性,但在某些場景下可能會帶來一些問題:
1. 前端顯示時可能出現精度丟失(JavaScript的Number類型最大安全整數為2^53-1)
2. 數據庫存儲空間浪費(特別是當數據量很大時)
3. 可讀性差,不利于人工識別和處理
4. 與其他系統對接時可能需要特殊處理
本文將深入分析這個問題,并提供多種解決方案。
## 一、問題根源分析
### 1.1 Mybatis-Plus默認ID生成策略
Mybatis-Plus默認使用`IdentifierGenerator`接口的實現類`DefaultIdentifierGenerator`來生成主鍵ID。其核心代碼如下:
```java
public class DefaultIdentifierGenerator implements IdentifierGenerator {
private final Sequence sequence;
public DefaultIdentifierGenerator() {
this.sequence = new Sequence();
}
@Override
public Long nextId(Object entity) {
return sequence.nextId();
}
}
這里的Sequence
類就是雪花算法的實現,生成的ID結構如下:
0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000
雪花算法生成的ID是一個64位的長整型,最大值可以達到2^63-1(9223372036854775807),這就是為什么我們經??吹胶荛L的數字ID。
@TableId(type = IdType.AUTO)
private Long id;
優點: - ID簡短且連續 - 查詢效率高 - 節省存儲空間
缺點: - 不適合分布式系統 - 分庫分表時會有問題 - 遷移數據時可能沖突
@TableId(type = IdType.UUID)
private String id;
優點: - 全局唯一 - 不依賴數據庫 - 適合分布式系統
缺點: - 存儲空間大(32字符) - 無序導致索引效率低 - 可讀性差
可以使用去掉橫線的UUID(32位字符)或時間有序的UUID(如COMB UUID)
IdentifierGenerator
接口@Component
public class CustomIdGenerator implements IdentifierGenerator {
@Override
public Long nextId(Object entity) {
// 實現自定義ID生成邏輯
return generateShortId();
}
private Long generateShortId() {
// 示例:使用時間戳+隨機數生成較短ID
return System.currentTimeMillis() % 1000000000 +
ThreadLocalRandom.current().nextInt(10000);
}
}
Mybatis-Plus提供了多種ID生成策略:
public enum IdType {
AUTO(0), // 數據庫自增
NONE(1), // 無狀態
INPUT(2), // 手動輸入
ASSIGN_ID(3), // 分配ID(默認雪花算法)
ASSIGN_UUID(4); // 分配UUID
}
可以使用ASSIGN_ID
并自定義ID生成器:
@Bean
public IdentifierGenerator idGenerator() {
return entity -> {
// 自定義ID生成邏輯
};
}
如果不想修改后端ID生成策略,可以在前端進行處理:
// 將長ID轉為字符串
const idString = bigId.toString();
// 使用BigInt
const bigId = BigInt(response.data.id);
// 格式化顯示
function formatLongId(id) {
return id.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
推薦使用數據庫自增ID(IdType.AUTO
)
方案 | ID長度 | 唯一性 | 有序性 | 存儲空間 | 適用場景 |
---|---|---|---|---|---|
雪花算法 | 19-20位數字 | 全局 | 時間有序 | 8字節 | 分布式系統 |
數據庫自增 | 1-10位數字 | 單表 | 完全有序 | 通常4字節 | 單機應用 |
UUID | 32/36字符 | 全局 | 無序 | 16字節 | 簡單分布式系統 |
自定義短ID | 可定制 | 看實現 | 看實現 | 通常4-8字節 | 特殊需求場景 |
@Component
public class RedisIdGenerator implements IdentifierGenerator {
@Autowired
private RedisTemplate<String, Long> redisTemplate;
@Override
public Long nextId(Object entity) {
String key = "id:" + entity.getClass().getSimpleName();
return redisTemplate.opsForValue().increment(key);
}
}
public class TimestampIdGenerator implements IdentifierGenerator {
private static final int RANDOM_BITS = 12;
private static final int MAX_RANDOM = 1 << RANDOM_BITS;
private int counter = 0;
@Override
public synchronized Long nextId(Object entity) {
long timestamp = System.currentTimeMillis() / 1000;
counter = (counter + 1) % MAX_RANDOM;
return (timestamp << RANDOM_BITS) | counter;
}
}
Mybatis-Plus默認的長ID生成策略是為了滿足分布式系統需求而設計的,但在實際應用中可能會帶來一些問題。本文介紹了五種解決方案:
開發者應根據實際業務場景、系統架構和性能需求選擇合適的方案。對于大多數分布式系統,雪花算法仍然是首選,但可以通過本文介紹的方法進行優化或替換。
希望本文能幫助讀者更好地理解和解決Mybatis-Plus中的長ID問題,構建更高效的數據存儲方案。 “`
這篇文章共計約2600字,詳細分析了Mybatis-Plus自動生成長ID的問題根源,提供了五種解決方案,并給出了實現示例和不同場景下的選擇建議。文章采用Markdown格式,包含代碼塊、表格等元素,便于閱讀和理解。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。