SpringBoot 装饰器@TableField原理解析

 更新时间:2025年09月10日 14:54:56   作者:司南锤  
本文解析了MyBatis-Plus的@TableField注解,用于非主键字段与数据库列的映射及行为控制,涵盖自动填充、乐观锁、多租户等企业级功能,提供使用技巧、常见问题及示例代码,感兴趣的朋友跟随小编一起看看吧

1. 开胃菜:一句话认识 @TableField

@TableField 是 MyBatis-Plus 提供的字段级注解,用于非主键字段与数据库列的显式绑定行为控制
记住两个关键字:“非主键”“行为控制”——这是它与 @TableId 的核心差异。

2. 为什么需要它?

场景不用 @TableField 的问题用了 @TableField 的收益
实体字段名与列名不一致默认下划线转驼峰失效显式指定 value="user_name"
实体属性非数据库字段MP 会无脑拼接,SQL 报错exist=false 排除
敏感字段不允许查询查询会返回密码select=false 自动屏蔽
插入/更新时要填充手动 set 易遗漏fill=FieldFill.INSERT 自动填充
乐观锁版本号需要手动判断version=true 一键启用

3. 快速上手:5 个最常用的属性

@Data
@TableName("t_user")
public class User {
    @TableId(type = IdType.AUTO)
    private Long id;
    // 1. 列名不一致
    @TableField("user_name")
    private String name;
    // 2. 虚拟字段,不持久化
    @TableField(exist = false)
    private String token;
    // 3. 查询时不返回
    @TableField(select = false)
    private String password;
    // 4. 插入自动写入
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;
    // 5. 更新自动写入
    @TableField(fill = FieldFill.UPDATE)
    private LocalDateTime updateTime;
    // 6. 乐观锁
    @Version
    @TableField("version")
    private Integer version;
}

4. 源码级剖析:MP 如何把注解变成 SQL

4.1 解析入口

TableInfoHelper#initTableInfo → 反射读取所有字段 → 构建 TableFieldInfo 列表。

4.2 SQL 拼接

AbstractSqlInjector 注入通用 CRUD 方法 →
DefaultSqlProviderTableFieldInfo 生成 SQL 片段 →
select=false 的字段被主动剔除,exist=false 的字段直接忽略。

4.3 填充与乐观锁

MetaObjectHandler 接口处理 FieldFill
MybatisPlusInterceptor 内的 OptimisticLockerInnerInterceptor 处理 @Version

5. 企业级高阶玩法

5.1 动态过滤字段 —— 防止数据越权

// 场景:普通用户不能查看薪资字段
@TableField(select = false, condition = "%s != 'admin'")
private BigDecimal salary;

配合 TenantLineInterceptor 可实现动态列级权限

5.2 加密存储 —— 自定义 TypeHandler

@TableField(typeHandler = AesTypeHandler.class)
private String idCard;

插入自动加密,查询自动解密,业务代码零侵入

5.3 多租户隔离 —— 租户字段加索引

@TableField("tenant_id")
@InterceptorIgnore(tenantLine = "true") // 跳过插件,避免死循环
private Long tenantId;

6. 高频踩坑 & 排查清单

现象根因正确姿势
更新时 version 不生效实体里 version 为 null先查后改,或者手动 set
虚拟字段被持久化忘记写 exist=false加上即可
select=false 依然查出手写 SQL 未使用 MP 条件构造器LambdaQueryWrapperSqlSelectInterceptor
填充不生效没实现 MetaObjectHandler@Component 实现接口

7. 和 Spring 注解的“梦幻联动”

@Component
public class MyMetaHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        // Spring 容器直接注入
        this.strictInsertFill(metaObject, "createTime", 
                              LocalDateTime.class, LocalDateTime.now());
    }
}

@TableField 负责标记,Spring 负责注入,两者解耦,符合单一职责。

8. 总结:一张脑图记住 @TableField

@TableField
├─ value          映射列名
├─ exist          是否持久化
├─ select         是否参与查询
├─ fill           自动填充策略
├─ update         自定义 set 片段
├─ condition      动态条件
├─ typeHandler    类型转换
└─ keepGlobalFormat 保留全局格式

9. 一键复制即可跑的最小 Demo

GitHub:https://github.com/YOUR_NAME/mp-tablefield-demo
分支:feature/tablefield-demo
包含:加密、乐观锁、多租户、自动填充 4 大示例,Maven 一键启动。

10. 评论区 FAQ 预览(提前回答)

Q1@TableField@Column 有什么区别?
A:后者是 JPA 规范,只在 Hibernate 生效;前者是 MyBatis-Plus 专用,功能更强。

Q2:能否在 Kotlin data class 使用?
A:可以,但字段必须声明为 var,否则无法填充。

Q3:性能会下降吗?
A:解析结果缓存到 TableInfo,运行期零反射,性能损耗 < 1%。

到此这篇关于一文讲透一个 SpringBoot 装饰器 —— @TableField的文章就介绍到这了,更多相关SpringBoot 装饰器@TableField内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • BaseDao封装JavaWeb的增删改查的实现代码

    BaseDao封装JavaWeb的增删改查的实现代码

    Basedao 是一种基于数据访问对象(Data Access Object)模式的设计方法,它是一个用于处理数据库操作的基础类,负责封装数据库访问的底层操作,提供通用的数据库访问方法,本文给大家介绍了BaseDao封装JavaWeb的增删改查的实现代码,需要的朋友可以参考下
    2024-03-03
  • Java使用POI导出Excel(二):多个sheet

    Java使用POI导出Excel(二):多个sheet

    这篇文章介绍了Java使用POI导出Excel的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-10-10
  • SpringBoot可视化监控的具体应用

    SpringBoot可视化监控的具体应用

    最近越发觉得,任何一个系统上线,运维监控都太重要了,本文介绍了SpringBoot可视化监控的具体应用,分享给大家,有兴趣的同学可以参考一下
    2021-06-06
  • Java抽象的本质解析

    Java抽象的本质解析

    对于面向对象编程来说,抽象是它的一大特征之一,在 Java 中可以通过两种形式来体现OOP的抽象:接口和抽象类,下面这篇文章主要给大家介绍了关于Java基础抽象的相关资料,需要的朋友可以参考下
    2022-03-03
  • 深入理解Java反射

    深入理解Java反射

    在理解反射原理之前先要搞清类型信息。接下来通过本文给大家介绍java反射的深入理解,非常不错,具有参考借鉴价值,感兴趣的朋友一起看下吧
    2016-07-07
  • 在Java中使用基本的正则表达式

    在Java中使用基本的正则表达式

    这篇文章主要介绍了在Java中使用基本的正则表达式,本文通过简要的案例,说明了很多场景下的正则表达式的用法,列出了正则表达式匹配规则的表格,需要的朋友可以参考下
    2021-07-07
  • Mock和@InjectMocks的区别及说明

    Mock和@InjectMocks的区别及说明

    @Mock和@InjectMocks是Mockito框架中的两个注解,前者用于创建模拟对象,后者用于将模拟对象注入到被测试类中
    2024-11-11
  • SpringBoot 使用 OpenAPI3 规范整合 knife4j的详细过程

    SpringBoot 使用 OpenAPI3 规范整合 knife4j的详细过程

    Swagger工具集使用OpenAPI规范,可以生成、展示和测试基于OpenAPI规范的API文档,并提供了生成客户端代码的功能,本文给大家介绍SpringBoot使用OpenAPI3规范整合knife4j的详细过程,感兴趣的朋友跟随小编一起看看吧
    2023-12-12
  • SpringCloud openfeign相互调用实现方法介绍

    SpringCloud openfeign相互调用实现方法介绍

    在springcloud中,openfeign是取代了feign作为负载均衡组件的,feign最早是netflix提供的,他是一个轻量级的支持RESTful的http服务调用框架,内置了ribbon,而ribbon可以提供负载均衡机制,因此feign可以作为一个负载均衡的远程服务调用框架使用
    2022-11-11
  • 解决IDEA target文件夹越来越大的问题

    解决IDEA target文件夹越来越大的问题

    这篇文章主要介绍了解决IDEA target文件夹越来越大的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02

最新评论