MyBatis-Plus提供的核心注解
MyBatis-Plus 提供了一系列核心注解来简化实体类与数据库表的映射配置,能够实现无需大量 XML 配置即可完成字段映射、主键策略、逻辑删除等核心功能。
下面我们按使用场景分类介绍一些 MyBatis-Plus 最常用的核心注解,在此之前需要保证环境中有如下内容:
数据库有user表,实体类为User,Mapper 接口继承 BaseMapper<User>

java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
java
public interface UserService extends IService<User> {
}
下面介绍 MyBatis-Plus 常用的 @TableName、@TableId、@TableField、@TableLogic 这几个注解的具体内容。
表映射注解@TableName
@TableName 是 MyBatis-Plus 它提供的表映射核心注解,核心作用能够灵活指定实体类对应的数据库表信息,是 MP 实现 "无 SQL 开发" 的基础映射配置手段。
拆解测试场景的核心逻辑
第一步:初始测试
编写 CRUD 测试,能正常查询user表数据,无异常,如图

即 MP 无需显式指定表名,会由BaseMapper的泛型对应的实体类,自动确定要操作的表名,具体流程和规则如下:
当 UserMapper 继承 BaseMapper<User> 时,MP 在应用启动阶段会通过反射解析 BaseMapper<T> 的泛型实参,精准获取到泛型对应的实体类 Class 对象,再按默认规则生成表名,当调用 BaseMapper 的 CRUD 方法时,会将默认规则生成的表名自动拼接进动态生成的 SQL 语句中。
生成表名的默认规则:
- 若实体类名无驼峰结构,直接将类名转为全小写作为表名(如User→user、student→student);
- 若实体类名包含驼峰结构,则拆分驼峰并在大写字母前添加下划线,再转为全小写(如UserInfo→user_info、SysUser→sys_user);
- 若配置了 MP 全局表前缀(如table-prefix: t_),会在转换后的表名前自动拼接该前缀(如User→t_user);
第二步:修改表名
将数据库user表重命名为t_user,实体类、Mapper 代码完全不变,再次执行查询测试,抛出异常 Table 'mybatis_plus.user'doesn't exist

MP 仍按默认规则,将实体类User映射为表名user,但数据库中已无user表,只有t_user表,因此找不到表,报错。
第三步:添加@TableName注解
在实体类类型上添加 @TableName("t_user"),标识实体类对应的表为 t_user 表
java
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("t_user")
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
即可成功执行SQL语句

配置全局表前缀功能
全局表前缀配置功能本质是对 MP 表名映射默认规则的批量优化配置
开发中数据库表常做规范统一,例如需要所有业务表都加前缀。如果没有全局配置,按之前的规则,每个实体类都要手动加@TableName指定带前缀的表名,这种方式重复且繁琐,而 MP 的全局表前缀配置可以一次性给所有实体对应的表名加统一前缀,省去逐个标注@TableName的工作量。
application.yml 中配置 MP 的全局表前缀:

为验证效果,我们需要先将 @TableName("t_user") 注解注释掉,再运行测试类,执行成功

优先级:@TableName 显式指定 > 全局表前缀 + 默认规则 > 纯默认规则。
主键映射注解@TableId
@TableId 是 MyBatis-Plus 提供的主键映射核心注解,专门用于标记实体类中对应数据库表主键列的属性,解决主键属性名与表主键列名不一致、自定义主键生成策略两大核心问题。
核心作用包含三方面:一是作为 MP 识别主键字段的关键依据,明确区分实体中的主键字段与普通字段;二是通过 value 属性自定义实体主键字段与数据库表主键字段的映射关系,精准解决两者字段名不一致的问题;三是通过 type 属性指定主键生成策略。
需要注意的是 @TableId 注解仅可标注在实体类的单个字段上,因为一个实体类仅支持标记一个主键字段。
拆解测试场景的核心逻辑
场景1:实体主键名 = 数据库主键名 ≠ id
例如实体主键字段是 uid,数据库表主键也是 uid,产生报错 Field 'uid' doesn't have a default value

数据库设计内容图下:

MyBatis-Plus 内置的主键字段默认名为 id 的规则,未识别出 uid 是主键字段,导致插入数据时未给 uid 赋值,而数据库表的 uid 主键字段既无默认值、也未开启自增,数据库无法确定 uid 的值,因此抛出字段无默认值的异常。
java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
@TableId
private Long uid;
private String name;
private Integer age;
private String email;
}
在实体类中 uid 属性上添加 @TableId 注解,将其标识为主键,即可成功执行SQL语句

场景2:实体主键名 ≠ 数据库主键名
例如实体主键字段是 id,数据库表主键也是 uid,产生报错 Unknown column 'id' in 'field list'

在实体类中 id 属性上添加 @TableId 注解,此时仍然产生报错 Unknown column 'id' in 'field list'。
因为此时 MyBatis-Plus 仍然会将 id 作为表的主键进行操作,而表中表示主键的是字段是 uid。
所以需要显式指定 @TableId 注解的 value 属性值,指定其值为表中的主键字段,使用 @TableId("uid") 或 @TableId(value="uid")。
java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
@TableId("uid")
private Long id;
private String name;
private Integer age;
private String email;
}

场景3:type = IdType.ASSIGN_ID
type 值默认为IdType.ASSIGN_ID,这是基于雪花算法的策略生成数据id,与数据库id是否设置自增无关

插入时无需设置id,MP自动获取自增值并回填19位长整型ID,数据库内容分如下:

场景4:type = IdType.AUTO
type = IdType.AUTO 即使用数据库的自增策略,注意,该类型请确保数据库设置 id 自增
若数据库未设置 id 自增,且设置 type = IdType.AUTO,则会出现报错

数据库设置 id 自增

执行测试方法


配置全局主键策略
若项目中所有实体的主键生成策略统一,可在配置文件中设置全局主键策略,无需在每个实体的 @TableId 中指定 type

配置后,实体类的 @TableId 可简化为
java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
@TableId(value = "uid")
private Long id;
private String name;
private Integer age;
private String email;
}
普通字段映射注解@TableField
@TableField 是 MyBatis-Plus 提供的字段级映射注解,用于补充 @TableName,解决实体类属性与数据库表字段的映射问题,包括字段名不一致、字段是否参与 CRUD、字段自动填充、查询 / 更新策略等场景。
拆解测试场景的核心逻辑
情况1:默认命名规则
若实体类中的属性使用的是驼峰命名风格,而表中的字段使用的是下划线命名风格
例如实体类属性userName,表中字段user_name
此时MyBatis-Plus会自动将下划线命名风格转化为驼峰命名风格
情况2:不符合默认命名规则
若实体类中的属性和表中的字段不满足默认命名规则
例如实体类属性name ,表中字段username
此时需要在实体类属性上使用@TableField("username")设置属性所对应的字段名
java
@TableField(value = "username")
private String name;
场景 3:实体包含非数据库字段(临时属性)
实体中有时会有临时计算的属性,不需要映射到数据库表,需设置 exist=false,否则 MP 会尝试查询该字段,导致 SQL 报错
java
// 非数据库字段:临时存储加密后的密码
@TableField(exist = false)
private String passwordMd5;
等
逻辑删除字段注解@TableLogic
@TableLogic 是 MyBatis-Plus 专门用于标记逻辑删除字段的注解,核心作用是实现逻辑删除(也常称假删除/软删除)而非物理删除。
即调用 MP 自带的 delete 类方法时,不直接删除表记录,而是更新该注解标记的逻辑删除字段的值标记为已删除,因此这条数据仍能在数据库中查到;调用 MP 自带的 select 类方法时,会自动拼接过滤条件过滤已标记删除的记录,无需手动在 SQL 中加该过滤条件(若手写 SQL/XML 需手动处理逻辑删除规则)。
@TableLogic 的 value(未删除值)和 delval(已删除值)这两个属性,可以填写数字或字符串,MyBatis-Plus 会根据实体类中逻辑删除字段的实际数据类型,自动将注解里填写的属性值转换成匹配的类型,无需手动进行类型转换,最终生成的 SQL 能适配数据库字段类型。
实体类在该字段上添加注解
java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
@TableId(value = "uid")
private Long id;
private String name;
private Integer age;
private String email;
@TableLogic(value = "0", delval = "1")
private Integer deleted;
}
数据库添加 delete 字段

测试逻辑删除
java
@Test
public void deleteById(){
int res = userMapper.deleteById(1998074992361287683L);
System.out.println("受影响的行数:"+res);
}
}

调用 MP 自带的 deleteById/deleteBatchIds 等删除方法时,SQL 从 DELETE 自动转为 UPDATE,更新逻辑删除字段


调用 MP 自带的 select/get 等查询方法时,自动拼接 WHERE 逻辑删除字段=未删除值,无需手动加条件
配置全局逻辑删除字段
若项目中所有表的逻辑删除字段规则统一,可在配置文件中全局配置,实体类只需加 @TableLogic,且无需指定属性

实体类可简化为
java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
@TableId(value = "uid")
private Long id;
private String name;
private Integer age;
private String email;
// 仅标记注解,使用全局配置的规则
@TableLogic
private Integer deleted;
}
为验证效果,我们再运行测试类,执行成功
