MyBatisPlus主键策略及自定义主键
半塘 2024/1/15 MyBatisPlus框架
# 1、主键配置
在注解章节中我们知道主键类型可以设置如下:
值 | 描述 |
---|---|
AUTO | 数据库 ID 自增 |
NONE | 无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT) |
INPUT | insert 前自行 set 主键值 |
ASSIGN_ID | 分配 ID(主键类型为 Number(Long 和 Integer)或 String)(since 3.3.0),使用接口IdentifierGenerator的方法nextId(默认实现类为DefaultIdentifierGenerator雪花算法) |
ASSIGN_UUID | 分配 UUID,主键类型为 String(since 3.3.0),使用接口IdentifierGenerator的方法nextUUID(默认 default 方法) |
@Data
@TableName("student")
public class StudentPO {
@TableId(value = "id",type = IdType.AUTO)
private Long id;
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
ASSIGN_ID:雪花算法手动构建
// 批量或者并发使用
IdentifierGenerator identifierGenerator=new DefaultIdentifierGenerator();
System.out.println(identifierGenerator.nextId(new Object()));
// 非批量并无并发时可用
System.out.println(IdWorker.getId());
1
2
3
4
5
6
2
3
4
5
6
# 2、主键策略
主键策略是指数据库中主键的生成和管理方式。
# 2.1、主键策略使用规则
- 主键生成策略必须使用 INPUT
- 支持父类定义 @KeySequence 子类继承使用
- 如果内置支持不满足你的需求,可实现 IKeyGenerator 接口来进行扩展
# 2.2、内置主键策略
MyBatis-Plus 提供了多种内置主键策略,可以根据不同的需求选择合适的主键策略:
- DB2KeyGenerator:适用于DB2数据库,自动为新记录生成唯一主键。
- H2KeyGenerator:适用于H2内存数据库,同样自动生成唯一主键。
- KingbaseKeyGenerator:适用于Kingbase数据库,根据其特性自动生成主键。
- OracleKeyGenerator:适用于Oracle数据库,使用序列为新记录生成唯一主键。
- PostgreKeyGenerator:适用于PostgreSQL数据库,同样使用序列来生成主键。
# 3、主键策略配置
# 3.1、Spring Boot 配置
- 方式一:配置类配置
@Bean
public IKeyGenerator keyGenerator() {
return new OracleKeyGenerator();
}
1
2
3
4
2
3
4
- 方式二:通过 MybatisPlusPropertiesCustomizer 自定义
@Bean
public MybatisPlusPropertiesCustomizer plusPropertiesCustomizer() {
return plusProperties -> plusProperties.getGlobalConfig().getDbConfig().setKeyGenerator(new H2KeyGenerator());
}
1
2
3
4
2
3
4
# 3.2、Spring 配置
- XML 配置
<bean id="globalConfig" class="com.baomidou.mybatisplus.core.config.GlobalConfig">
<property name="dbConfig" ref="dbConfig"/>
</bean>
<bean id="dbConfig" class="com.baomidou.mybatisplus.core.config.GlobalConfig.DbConfig">
<property name="keyGenerator" ref="keyGenerator"/>
</bean>
<bean id="keyGenerator" class="com.baomidou.mybatisplus.extension.incrementer.H2KeyGenerator"/>
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
- 注解配置
@Bean
public GlobalConfig globalConfig() {
GlobalConfig conf = new GlobalConfig();
conf.setDbConfig(new GlobalConfig.DbConfig().setKeyGenerator(new H2KeyGenerator()));
return conf;
}
1
2
3
4
5
6
2
3
4
5
6
# 4、使用主键策略
这里以Oracle数据库为例,其他数据库的主键策略配置类似。
- 配置类配置主键策略
@Bean
public IKeyGenerator keyGenerator() {
return new OracleKeyGenerator();
}
1
2
3
4
2
3
4
- Oracle数据库创建序列
-- 创建序列
CREATE SEQUENCE seq_student
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 10
NOCYCLE
ORDER;
-- 测试序列
SELECT seq_student.NEXTVAL FROM dual;
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
- 实体类使用注解配置序列
// seq_student为序列名
@KeySequence(value = "seq_student", clazz = Long.class)
public class YourEntity {
@TableId(value = "ID", type = IdType.INPUT)
private Long id;
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 5、自定义主键策略
接口IdentifierGenerator
可以重写三个方法,分别为:assignId、nextId、nextUUID。生成的主键算法不一样。
方法 | 主键生成策略 | 主键类型 | 说明 |
---|---|---|---|
nextId | ASSIGN_ID | Long,Integer,String | 支持自动转换为 String 类型,但数值类型不支持自动转换,需精准匹配,例如返回 Long,实体主键就不支持定义为 Integer |
nextUUID | ASSIGN_UUID | String | 默认不含中划线的 UUID 生成 |
# 5.1、自定义主键策略类
实现接口IdentifierGenerator
public class CustomIdGenerator implements IdentifierGenerator{
/**
* 雪花算法,这里不重写
*/
@Override
public boolean assignId(Object idValue) {
return IdentifierGenerator.super.assignId(idValue);
}
/**
* 重写生成分布式主键
*/
@Override
public Long nextId(Object entity) {
//可以将当前传入的class全类名来作为bizKey,或者提取参数来生成bizKey进行分布式Id调用生成.
String bizKey = entity.getClass().getName();
//根据bizKey调用分布式ID生成
long id = new DistributedIDGenerator((long) "product001".hashCode()).generateId();
//返回生成的id值即可.
return id;
}
/**
* 默认不含中划线的 UUID 生成,这里不重写
*/
@Override
public String nextUUID(Object entity) {
return IdentifierGenerator.super.nextUUID(entity);
}
}
// 根据bizKey生成分布式ID
class DistributedIDGenerator {
private final AtomicInteger sequence = new AtomicInteger(0);
private final Long bizKey;
public DistributedIDGenerator(Long bizKey) {
this.bizKey = bizKey;
}
public synchronized Long generateId() {
int currentSequence = sequence.incrementAndGet();
return bizKey + currentSequence + UUID.randomUUID().hashCode();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# 5.2、SpringBoot方式配置
- 方式一:配置为组件直接扫描
直接加@Component声明为组件,然后扫描即可。
@Component
public class CustomIdGenerator implements IdentifierGenerator{
}
1
2
3
4
2
3
4
- 方式二:使用配置类
@Bean
public IdentifierGenerator idGenerator() {
return new CustomIdGenerator();
}
1
2
3
4
2
3
4
- 方式三:通过 MybatisPlusPropertiesCustomizer 自定义
@Bean
public MybatisPlusPropertiesCustomizer plusPropertiesCustomizer() {
return plusProperties -> plusProperties.getGlobalConfig().setIdentifierGenerator(new CustomIdGenerator());
}
1
2
3
4
2
3
4
# 5.3、Spring方式配置
- 方式一: XML 配置
<bean name="customIdGenerator" class="com.baomidou.samples.incrementer.CustomIdGenerator"/>
<bean id="globalConfig" class="com.baomidou.mybatisplus.core.config.GlobalConfig">
<property name="identifierGenerator" ref="customIdGenerator"/>
</bean>
1
2
3
4
5
2
3
4
5
- 方式二:注解配置
@Bean
public GlobalConfig globalConfig() {
GlobalConfig conf = new GlobalConfig();
conf.setIdentifierGenerator(new CustomIdGenerator());
return conf;
}
1
2
3
4
5
6
2
3
4
5
6