MyBatis-Plus自定义ID生成策略
MyBatis-Plus是一个基于MyBatis的增强工具,提供了许多方便的功能,其中包括自动生成主键ID。虽然MyBatis-Plus默认提供了多种ID生成策略,但在某些特定场景下,我们可能需要自定义ID生成策略。本文将详细介绍如何在MyBatis-Plus中实现自定义ID生成策略。

一、为什么需要自定义ID生成策略?
在某些情况下,业务需求可能要求我们使用特定的ID生成规则,例如:
- 分布式系统中的全局唯一ID
- 高并发下的高性能ID生成
- 符合特定业务逻辑的ID格式
为了满足这些需求,我们可以通过自定义ID生成策略来实现。
二、自定义ID生成策略的实现步骤
1. 引入必要依赖
在 pom.xml中添加MyBatis-Plus依赖:
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3.4</version>
</dependency>
2. 实现自定义ID生成器
自定义ID生成器需要实现MyBatis-Plus提供的 IdentifierGenerator接口。以下是一个示例实现,基于雪花算法生成ID:
package com.example.demo.config;
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import org.springframework.stereotype.Component;
import java.net.InetAddress;
import java.net.UnknownHostException;
@Component
public class CustomIdGenerator implements IdentifierGenerator {
private final long workerId;
private final long datacenterId;
public CustomIdGenerator() {
this.workerId = getWorkerId();
this.datacenterId = getDatacenterId();
}
@Override
public Long nextId(Object entity) {
return SnowflakeIdUtils.nextId(workerId, datacenterId);
}
private long getWorkerId() {
// 根据实际需求实现获取workerId的逻辑
return 1L;
}
private long getDatacenterId() {
// 根据实际需求实现获取datacenterId的逻辑
return 1L;
}
}
3. 实现雪花算法
雪花算法是一种高效的分布式ID生成算法,能够保证ID的全局唯一性。以下是一个基于雪花算法的ID生成工具类:
package com.example.demo.config;
public class SnowflakeIdUtils {
private static final long TWEPOCH = 1288834974657L;
private static final long WORKER_ID_BITS = 5L;
private static final long DATACENTER_ID_BITS = 5L;
private static final long MAX_WORKER_ID = ~(-1L << WORKER_ID_BITS);
private static final long MAX_DATACENTER_ID = ~(-1L << DATACENTER_ID_BITS);
private static final long SEQUENCE_BITS = 12L;
private static final long WORKER_ID_SHIFT = SEQUENCE_BITS;
private static final long DATACENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;
private static final long TIMESTAMP_LEFT_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATACENTER_ID_BITS;
private static final long SEQUENCE_MASK = ~(-1L << SEQUENCE_BITS);
private long lastTimestamp = -1L;
private long sequence = 0L;
public static synchronized long nextId(long workerId, long datacenterId) {
if (workerId > MAX_WORKER_ID || workerId < 0) {
throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", MAX_WORKER_ID));
}
if (datacenterId > MAX_DATACENTER_ID || datacenterId < 0) {
throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", MAX_DATACENTER_ID));
}
long timestamp = timeGen();
if (timestamp < lastTimestamp) {
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
}
if (lastTimestamp == timestamp) {
sequence = (sequence + 1) & SEQUENCE_MASK;
if (sequence == 0) {
timestamp = tilNextMillis(lastTimestamp);
}
} else {
sequence = 0L;
}
lastTimestamp = timestamp;
return ((timestamp - TWEPOCH) << TIMESTAMP_LEFT_SHIFT) |
(datacenterId << DATACENTER_ID_SHIFT) |
(workerId << WORKER_ID_SHIFT) |
sequence;
}
private static long tilNextMillis(long lastTimestamp) {
long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
}
private static long timeGen() {
return System.currentTimeMillis();
}
}
4. 配置MyBatis-Plus使用自定义ID生成器
在Spring Boot配置类中注册自定义ID生成器:
package com.example.demo.config;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyBatisPlusConfig {
@Bean
public GlobalConfig globalConfig() {
GlobalConfig globalConfig = new GlobalConfig();
globalConfig.setIdentifierGenerator(new CustomIdGenerator());
return globalConfig;
}
}
三、应用自定义ID生成策略
在实体类上配置主键生成策略,使用自定义ID生成器:
package com.example.demo.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.IdType;
import lombok.Data;
@Data
public class User {
@TableId(type = IdType.ASSIGN_ID)
private Long id;
private String name;
private String email;
}
四、验证自定义ID生成策略
编写测试代码,验证自定义ID生成策略是否生效:
package com.example.demo;
import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class CustomIdGeneratorTest {
@Autowired
private UserMapper userMapper;
@Test
public void testInsertUser() {
User user = new User();
user.setName("John Doe");
user.setEmail("john.doe@example.com");
userMapper.insert(user);
System.out.println("Inserted user ID: " + user.getId());
}
}
分析说明表
| 步骤 | 说明 | 示例 |
|---|---|---|
| 引入必要依赖 | 在 pom.xml中添加MyBatis-Plus依赖 |
<dependency>...</dependency> |
| 实现自定义ID生成器 | 实现 IdentifierGenerator接口,自定义ID生成逻辑 |
CustomIdGenerator |
| 实现雪花算法 | 编写基于雪花算法的ID生成工具类 | SnowflakeIdUtils |
| 配置MyBatis-Plus | 在Spring配置类中注册自定义ID生成器 | MyBatisPlusConfig |
| 应用自定义ID生成策略 | 在实体类上配置主键生成策略 | User |
| 验证自定义ID生成 | 编写测试代码,验证自定义ID生成策略 | CustomIdGeneratorTest |
总结
通过上述步骤,我们详细介绍了如何在MyBatis-Plus中实现自定义ID生成策略。自定义ID生成器能够满足特定业务需求,确保ID的全局唯一性和高效生成。希望本文能够为您在使用MyBatis-Plus时提供实用的参考,帮助您实现更加灵活和高效的ID生成策略。


