一、核心概念

概念 说明
作用 标识实体类的主键字段,用于数据库主键与实体属性的映射
核心属性 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 无策略,需手动设置 不推荐

三、常见错误与解决方案

  1. 主键字段映射失败
    现象Insert时提示“字段不存在”
    原因@TableId("db_id") 配置的字段名与数据库不一致
    解决:检查数据库主键字段名是否与注解中value值一致

  2. 自增主键配置错误
    现象AUTO策略下ID未自增
    解决

    • 确保数据库主键勾选“自增”
    • 实体类配置:@TableId(type = IdType.AUTO)
  3. ASSIGN_ID重复问题
    现象分布式环境下ID冲突
    解决

    mybatis-plus:
      global-config:
        worker-id: 1 # 设置机器ID (0~31)
        datacenter-id: 1 # 数据中心ID (0~31)
    

四、关键注意事项

  1. 策略优先级
    @TableId > 全局配置,局部注解优先生效

  2. ASSIGN_ID精度问题
    JavaScript处理Long类型会丢失精度,返回给前端时应转为String:

    @JsonSerialize(using = ToStringSerializer.class)
    private Long id;
    
  3. INPUT模式必填
    使用IdType.INPUT时,必须手动设置ID值:

    User user = new User();
    user.setCustomId("20230801_001"); // 必须赋值
    userMapper.insert(user);
    

五、性能优化建议

  1. 索引优化

    • 使用ASSIGN_ID(有序Long)比ASSIGN_UUID(无序字符串)更利于B+树索引维护
  2. 批量插入
    insertBatch()代替循环插入,减少事务开销:

    List<User> users = ...;
    userService.saveBatch(users); // 批量提交
    
  3. 避免全表扫描
    查询时始终带上主键条件,如:

    userMapper.selectById(id); // ✅ 走主键索引
    

六、最佳实践

  1. 分布式系统

    // 默认策略(ASSIGN_ID),无需显式声明
    @TableId
    private Long id;
    
  2. 分库分表场景
    使用带有时间戳的ID生成策略(如雪花算法),避免跨分片查询

  3. 多主键处理
    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生成的配置细节,这是保证系统稳定性的关键。