您好,登录后才能下订单哦!
# 怎么解决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),这就是为什么我们经常看到很长的数字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进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。