一、核心概念
概念 | 说明 |
---|---|
作用 | 标识实体类的主键字段,用于数据库主键与实体属性的映射 |
核心属性 | value (表主键字段名), type (主键生成策略) |
主键策略 | IdType.AUTO , ASSIGN_ID , ASSIGN_UUID , INPUT , NONE 等 |
二、详细操作步骤
1. 添加依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.0+</version>
</dependency>
2. 实体类配置
@Data
@TableName("user") // 指定表名
public class User {
// 场景1:主键字段名与属性名一致(默认)
@TableId(type = IdType.ASSIGN_ID)
private Long id;
// 场景2:主键字段名与属性名不一致
@TableId(value = "user_id", type = IdType.INPUT)
private String customId;
private String name;
}
3. 主键策略配置(全局)
# application.yml
mybatis-plus:
global-config:
db-config:
id-type: assign_id # 全局主键策略(优先级低于@TableId)
4. 常用主键策略对比
策略 | 说明 | 适用场景 |
---|---|---|
IdType.AUTO |
数据库自增(ID) | MySQL、PostgreSQL |
IdType.ASSIGN_ID |
雪花算法生成Long(19位) | 分布式系统(默认策略) |
IdType.ASSIGN_UUID |
生成32位UUID字符串 | 需要字符串ID的场景 |
IdType.INPUT |
手动输入ID | 业务自定义主键 |
IdType.NONE |
无策略,需手动设置 | 不推荐 |
三、常见错误与解决方案
主键字段映射失败
现象:Insert时提示“字段不存在”
原因:@TableId("db_id")
配置的字段名与数据库不一致
解决:检查数据库主键字段名是否与注解中value
值一致自增主键配置错误
现象:AUTO策略下ID未自增
解决:- 确保数据库主键勾选“自增”
- 实体类配置:
@TableId(type = IdType.AUTO)
ASSIGN_ID重复问题
现象:分布式环境下ID冲突
解决:mybatis-plus: global-config: worker-id: 1 # 设置机器ID (0~31) datacenter-id: 1 # 数据中心ID (0~31)
四、关键注意事项
策略优先级
@TableId > 全局配置
,局部注解优先生效ASSIGN_ID精度问题
JavaScript处理Long类型会丢失精度,返回给前端时应转为String:@JsonSerialize(using = ToStringSerializer.class) private Long id;
INPUT模式必填
使用IdType.INPUT
时,必须手动设置ID值:User user = new User(); user.setCustomId("20230801_001"); // 必须赋值 userMapper.insert(user);
五、性能优化建议
索引优化
- 使用
ASSIGN_ID
(有序Long)比ASSIGN_UUID
(无序字符串)更利于B+树索引维护
- 使用
批量插入
用insertBatch()
代替循环插入,减少事务开销:List<User> users = ...; userService.saveBatch(users); // 批量提交
避免全表扫描
查询时始终带上主键条件,如:userMapper.selectById(id); // ✅ 走主键索引
六、最佳实践
分布式系统
// 默认策略(ASSIGN_ID),无需显式声明 @TableId private Long id;
分库分表场景
使用带有时间戳的ID生成策略(如雪花算法),避免跨分片查询多主键处理
MyBatis-Plus不支持复合主键,需:- 方案1:新增单独主键字段
- 方案2:使用
@TableId
+@TableField
组合,并在SQL中手动处理
七、示例代码:完整流程
// 实体类
@Data
public class Order {
@TableId(value = "order_no", type = IdType.INPUT)
private String orderNo; // 业务主键(如:20230801_001)
private BigDecimal amount;
}
// 使用示例
Order order = new Order();
order.setOrderNo(IdUtil.getSnowflakeNextIdStr()); // 手动生成ID
order.setAmount(new BigDecimal("99.9"));
orderMapper.insert(order); // 插入数据
通过以上结构化说明,你可快速掌握@TableId
的核心用法,规避常见陷阱,并在实际项目中应用最佳实践。重点注意主键策略选择与分布式ID生成的配置细节,这是保证系统稳定性的关键。