MyBatis-Plus提供的核心注解

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;

}

为验证效果,我们再运行测试类,执行成功

相关推荐
光羽隹衡7 小时前
MySQL的安装
数据库·mysql
脸大是真的好~7 小时前
尚硅谷-mysql专项训练-数据库服务的优化-慢查询-EXPLAIN字段
数据库·mysql·性能优化
梦未7 小时前
Spring控制反转与依赖注入
java·后端·spring
喜欢流萤吖~7 小时前
Lambda 表达式
java
无限大67 小时前
验证码对抗史
后端
Dragon online7 小时前
数据分析师成长之路--从SQL恐惧到数据掌控者的蜕变
数据库·sql
ZouZou老师7 小时前
C++设计模式之适配器模式:以家具生产为例
java·设计模式·适配器模式
用户2190326527357 小时前
Java后端必须的Docker 部署 Redis 集群完整指南
linux·后端
曼巴UE57 小时前
UE5 C++ 动态多播
java·开发语言
VX:Fegn08957 小时前
计算机毕业设计|基于springboot + vue音乐管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·课程设计