在MyBatisPlus中,当你插入数据时,如果不希望自动使用雪花算法生成主键ID,你可以自定义主键策略。默认情况下,MyBatisPlus会为非Id类型的字段设置@TableId注解,并启用全局唯一ID生成器(如Snowflake)
时间: 2024-12-22 22:11:48 浏览: 372
在MyBatisPlus中,如果你不想让框架自动使用雪花算法生成主键,有几种处理方式:
1. **手动赋值**: 就像前面提到的,可以直接在创建对象时,对`@TableId`标注的字段赋一个已知的值,如`Long`类型的基本类型值或`UUID`。
```java
User user = new User();
user.setId(1L); // 自定义的ID
user.setName("John");
save(user); // save方法用于插入数据
```
2. **关闭全局ID生成**:虽然默认开启,但你可以在全局配置文件(通常在`GlobalConfig`中)中禁用它,然后明确每个实体类的主键生成规则。
3. **自定义主键策略**:如果需要更复杂的策略,可以创建一个自定义的`BaseService`或`GlobalConfiguration`子类,覆盖默认的ID生成方法。
```java
// 配置文件中禁用全局ID生成
public class GlobalConfig extends BaseGlobalConfig {
@Override
protected void initDataSource() {
super.initDataSource();
idGen().setUseGeneratedKey(false);
}
}
```
在插入时,记得在实体类上显式声明主键策略,比如`@TableId(value = "id", type = IdType.AUTO)`。
相关问题
mybatisplus的saveBatch方法自生成主键id重复
### MyBatisPlus `saveBatch` 方法主键 ID 重复的原因分析
在使用 MyBatisPlus 的批量保存方法 `saveBatch` 时,如果实体类中的主键字段(通常为 `id`)采用自动生成策略(如雪花算法或 UUID),可能会遇到主键冲突的情况。这通常是由于以下几个原因之一引起的:
#### 原因一:全局唯一标识符生成器配置不当
MyBatisPlus 提供了多种主键生成策略,其中最常用的是基于时间戳和机器码的雪花算法(Snowflake)。然而,在高并发场景下或者分布式环境中,如果没有正确配置雪花算法的时间偏移量和服务实例编号,则可能导致不同线程或服务节点生成相同的主键[^1]。
#### 厰象描述
当调用 `saveBatch(List<T> entityList)` 方法时,传入的对象列表中某些对象可能被分配到相同 ID,从而违反数据库表设计中的唯一约束条件并抛出异常。
---
### 解决方案
以下是针对上述问题的具体解决办法:
#### 方案一:调整 Snowflake 配置参数
可以通过修改 MyBatisPlus 中默认实现的 `IdWorker` 类来优化其工作方式。具体做法如下:
- 设置更大的 workerId 和 datacenterId 范围以减少碰撞概率;
- 如果项目运行于多台服务器上,则需确保每台机器拥有独立且唯一的 Worker Id[^2]。
```java
// 自定义 IdGenerator 实现类
@Component
public class CustomIdGenerator implements IdentifierGenerator {
private final SnowflakeIdWorker snowFlake;
public CustomIdGenerator() {
this.snowFlake = new SnowflakeIdWorker(1, 1); // 可根据实际需求设置不同的workerId和dataCenterId
}
@Override
public Number nextId(Object entity) {
return snowFlake.nextId();
}
}
```
随后,在 Spring Boot 应用程序启动类中标记该 Bean 注册生效即可。
---
#### 方案二:改用其他类型的主键生成机制
除了依赖内置的 Snowflake 外部工具外,还可以考虑引入第三方库比如 Twitter 开源版本的 Snowflake 或者直接切换成字符串形式的 UUID 来作为记录标识[^3]。
示例代码展示如何通过重写业务逻辑替换原有整数型主键结构:
```java
@Entity
public class ExampleEntity {
@TableId(type= IdType.ASSIGN_UUID)
private String id;
...
}
// 使用前无需额外处理,默认会自动填充合法UUID值给新创建条目
exampleMapper.insert(exampleInstance);
```
注意这里我们将原先是 Long 类型的数据列改为 VARCHAR 并指定长度足够容纳标准格式化后的 Universally Unique Identifiers 表达式串。
---
#### 方案三:手动控制批次提交大小
对于非常大规模数据集操作而言,单次请求尝试一次性插入过多行也可能间接引发此类错误消息提示。因此建议适当降低每次传递至底层 DAO 层面待执行 SQL 数组规模数量级,进而缓解潜在竞争状况发生几率[^4]。
例如可以将原始集合拆分为若干子集分别逐一完成持久化进程:
```java
int batchSize = 50; // 定义合理阈值界限
for (int i = 0; i < list.size(); i += batchSize){
List<ExampleEntity> subList = list.subList(i, Math.min(list.size(),i+batchSize));
exampleService.saveBatch(subList);
}
```
这样既能够保持较高吞吐率又能有效规避部分极端情况下产生的副作用影响。
---
### 总结
综上所述,MyBatisPlus 批量存储过程中出现主键重复现象的主要诱因在于当前所选用的身份识别编码体系未能完全满足特定应用场景下的功能诉求所致。对此可采取重新规划相关组件初始化流程、变更候选替代技术路线以及精细化管理事务边界等多种手段予以妥善应对处置。
mybatisplus varchar 主键 策略
### MyBatisPlus VARCHAR 类型主键生成策略
对于 `VARCHAR` 类型的主键,在 MyBatisPlus 中可以采用不同的生成策略。主要的方式有两种:
#### 1. 使用 UUID 作为主键
当希望使用包含字母和数字的独特字符串作为主键时,可以选择 `ASSIGN_UUID()` 方法。这种方式能够确保生成的 ID 是全球唯一标识符 (UUID),适用于需要高并发场景下的应用开发[^5]。
```java
@TableId(type = IdType.ASSIGN_UUID)
private String userId;
```
此方法会在每次创建新记录前自动生成一个新的 UUID 并赋给对应的字段。
#### 2. 自定义序列号或通过 Sequence 获取主键值
如果业务逻辑允许并且表结构支持,则还可以考虑利用 Oracle 的 `Sequence` 或者 MySQL 的替代方案来自增生成主键值。特别是当实体类中的主键属性被声明为 `String` 而不是数值类型的情况下[^2]。
为了实现这一点,通常需要编写额外的服务层代码来调用特定于数据库类型的 API 来获取下一个序号,并将其手动设置到待插入的对象实例上;或者也可以借助第三方库如 Apache Commons Lang 提供的帮助函数完成类似功能。
另外需要注意的是,如果没有特别指定主键生成方式的话,默认情况下 MyBatisPlus 将会使用雪花算法(Snowflake Algorithm),它同样能返回适合存储在 `VARCHAR` 字段内的字符串形式的结果[^4]。
阅读全文
相关推荐















