怎么解决Mybatis-Plus自动生成的数据库id过长问题

发布时间:2021-12-03 16:30:09 作者:iii
来源:亿速云 阅读:1471
# 怎么解决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.2 为什么ID会很长

雪花算法生成的ID是一个64位的长整型,最大值可以达到2^63-1(9223372036854775807),这就是为什么我们经常看到很长的数字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 推荐算法

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 分布式系统

3.3 需要良好可读性

3.4 高并发系统

四、性能与存储对比

方案 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格式,包含代码块、表格等元素,便于阅读和理解。

推荐阅读:
  1. php如何自动生成不重复的id
  2. 解决PATH环境变量过长问题

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

mybatis-plus

上一篇:mysql中整数数据类型tinyint怎么使用

下一篇:如何解析HBase冷热分离技术原理

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》