溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么解決Mybatis-Plus自動生成的數據庫id過長問題

發布時間:2021-12-03 16:30:09 來源:億速云 閱讀:1502 作者:iii 欄目:開發技術
# 怎么解決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
  • 1位符號位(始終為0)
  • 41位時間戳(毫秒級)
  • 10位機器ID(5位數據中心ID + 5位機器ID)
  • 12位序列號

1.2 為什么ID會很長

雪花算法生成的ID是一個64位的長整型,最大值可以達到2^63-1(9223372036854775807),這就是為什么我們經??吹胶荛L的數字ID。

二、解決方案

2.1 方案一:使用數據庫自增ID

2.1.1 配置方法

@TableId(type = IdType.AUTO)
private Long id;

2.1.2 優缺點分析

優點: - ID簡短且連續 - 查詢效率高 - 節省存儲空間

缺點: - 不適合分布式系統 - 分庫分表時會有問題 - 遷移數據時可能沖突

2.1.3 適用場景

  • 單機應用
  • 數據量不大的系統
  • 不需要分庫分表的場景

2.2 方案二:使用UUID

2.2.1 配置方法

@TableId(type = IdType.UUID)
private String id;

2.2.2 優缺點分析

優點: - 全局唯一 - 不依賴數據庫 - 適合分布式系統

缺點: - 存儲空間大(32字符) - 無序導致索引效率低 - 可讀性差

2.2.3 優化方案

可以使用去掉橫線的UUID(32位字符)或時間有序的UUID(如COMB UUID)

2.3 方案三:自定義ID生成器

2.3.1 實現步驟

  1. 實現IdentifierGenerator接口
  2. 注冊為Spring Bean
@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);
    }
}

2.3.2 推薦算法

  • 時間戳+自增序列
  • Redis INCR命令生成ID
  • 數據庫分段獲取ID

2.4 方案四:使用Mybatis-Plus的其他內置策略

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生成邏輯
    };
}

2.5 方案五:前端處理長ID問題

如果不想修改后端ID生成策略,可以在前端進行處理:

  1. 轉換為字符串傳輸
  2. 使用BigInt類型(ES2020+)
  3. 顯示時截斷或格式化
// 將長ID轉為字符串
const idString = bigId.toString();

// 使用BigInt
const bigId = BigInt(response.data.id);

// 格式化顯示
function formatLongId(id) {
    return id.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}

三、不同場景下的方案選擇

3.1 單機應用

推薦使用數據庫自增ID(IdType.AUTO

3.2 分布式系統

  • 對ID長度不敏感:繼續使用雪花算法
  • 需要較短ID:使用Redis生成ID或自定義算法

3.3 需要良好可讀性

  • 使用有意義的ID(如日期+序列號)
  • 使用較短的UUID變種

3.4 高并發系統

  • 避免使用數據庫自增ID
  • 考慮預生成ID池

四、性能與存儲對比

方案 ID長度 唯一性 有序性 存儲空間 適用場景
雪花算法 19-20位數字 全局 時間有序 8字節 分布式系統
數據庫自增 1-10位數字 單表 完全有序 通常4字節 單機應用
UUID 32/36字符 全局 無序 16字節 簡單分布式系統
自定義短ID 可定制 看實現 看實現 通常4-8字節 特殊需求場景

五、實現示例

5.1 基于Redis的自增ID生成器

@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);
    }
}

5.2 時間戳+隨機數生成器

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生成策略是為了滿足分布式系統需求而設計的,但在實際應用中可能會帶來一些問題。本文介紹了五種解決方案:

  1. 使用數據庫自增ID(適合單機應用)
  2. 使用UUID(簡單分布式方案)
  3. 自定義ID生成器(靈活應對各種需求)
  4. 使用其他內置策略(平衡各種需求)
  5. 前端處理方案(不改動后端的妥協方案)

開發者應根據實際業務場景、系統架構和性能需求選擇合適的方案。對于大多數分布式系統,雪花算法仍然是首選,但可以通過本文介紹的方法進行優化或替換。

七、擴展思考

  1. 如何設計一個既能保證分布式唯一性又比較短的ID?
  2. 在分庫分表場景下,ID生成策略應該如何選擇?
  3. 如何實現ID的可讀性與安全性的平衡?
  4. 未來是否有更好的分布式ID生成方案?

希望本文能幫助讀者更好地理解和解決Mybatis-Plus中的長ID問題,構建更高效的數據存儲方案。 “`

這篇文章共計約2600字,詳細分析了Mybatis-Plus自動生成長ID的問題根源,提供了五種解決方案,并給出了實現示例和不同場景下的選擇建議。文章采用Markdown格式,包含代碼塊、表格等元素,便于閱讀和理解。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女