SpringBoot 裝飾器@TableField原理解析
1. 開(kāi)胃菜:一句話認(rèn)識(shí) @TableField
@TableField 是 MyBatis-Plus 提供的字段級(jí)注解,用于非主鍵字段與數(shù)據(jù)庫(kù)列的顯式綁定與行為控制。
記住兩個(gè)關(guān)鍵字:“非主鍵”、“行為控制”——這是它與 @TableId 的核心差異。
2. 為什么需要它?
| 場(chǎng)景 | 不用 @TableField 的問(wèn)題 | 用了 @TableField 的收益 |
|---|---|---|
| 實(shí)體字段名與列名不一致 | 默認(rèn)下劃線轉(zhuǎn)駝峰失效 | 顯式指定 value="user_name" |
| 實(shí)體屬性非數(shù)據(jù)庫(kù)字段 | MP 會(huì)無(wú)腦拼接,SQL 報(bào)錯(cuò) | exist=false 排除 |
| 敏感字段不允許查詢(xún) | 查詢(xún)會(huì)返回密碼 | select=false 自動(dòng)屏蔽 |
| 插入/更新時(shí)要填充 | 手動(dòng) set 易遺漏 | fill=FieldFill.INSERT 自動(dòng)填充 |
| 樂(lè)觀鎖版本號(hào) | 需要手動(dòng)判斷 | version=true 一鍵啟用 |
3. 快速上手:5 個(gè)最常用的屬性
@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. 查詢(xún)時(shí)不返回
@TableField(select = false)
private String password;
// 4. 插入自動(dòng)寫(xiě)入
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
// 5. 更新自動(dòng)寫(xiě)入
@TableField(fill = FieldFill.UPDATE)
private LocalDateTime updateTime;
// 6. 樂(lè)觀鎖
@Version
@TableField("version")
private Integer version;
}4. 源碼級(jí)剖析:MP 如何把注解變成 SQL
4.1 解析入口
TableInfoHelper#initTableInfo → 反射讀取所有字段 → 構(gòu)建 TableFieldInfo 列表。
4.2 SQL 拼接
AbstractSqlInjector 注入通用 CRUD 方法 →DefaultSqlProvider 按 TableFieldInfo 生成 SQL 片段 →select=false 的字段被主動(dòng)剔除,exist=false 的字段直接忽略。
4.3 填充與樂(lè)觀鎖
MetaObjectHandler 接口處理 FieldFill;MybatisPlusInterceptor 內(nèi)的 OptimisticLockerInnerInterceptor 處理 @Version。
5. 企業(yè)級(jí)高階玩法
5.1 動(dòng)態(tài)過(guò)濾字段 —— 防止數(shù)據(jù)越權(quán)
// 場(chǎng)景:普通用戶(hù)不能查看薪資字段 @TableField(select = false, condition = "%s != 'admin'") private BigDecimal salary;
配合 TenantLineInterceptor 可實(shí)現(xiàn)動(dòng)態(tài)列級(jí)權(quán)限。
5.2 加密存儲(chǔ) —— 自定義 TypeHandler
@TableField(typeHandler = AesTypeHandler.class) private String idCard;
插入自動(dòng)加密,查詢(xún)自動(dòng)解密,業(yè)務(wù)代碼零侵入。
5.3 多租戶(hù)隔離 —— 租戶(hù)字段加索引
@TableField("tenant_id")
@InterceptorIgnore(tenantLine = "true") // 跳過(guò)插件,避免死循環(huán)
private Long tenantId;6. 高頻踩坑 & 排查清單
| 現(xiàn)象 | 根因 | 正確姿勢(shì) |
|---|---|---|
| 更新時(shí) version 不生效 | 實(shí)體里 version 為 null | 先查后改,或者手動(dòng) set |
| 虛擬字段被持久化 | 忘記寫(xiě) exist=false | 加上即可 |
| select=false 依然查出 | 手寫(xiě) SQL 未使用 MP 條件構(gòu)造器 | 用 LambdaQueryWrapper 或 SqlSelectInterceptor |
| 填充不生效 | 沒(méi)實(shí)現(xiàn) MetaObjectHandler | 加 @Component 實(shí)現(xiàn)接口 |
7. 和 Spring 注解的“夢(mèng)幻聯(lián)動(dòng)”
@Component
public class MyMetaHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
// Spring 容器直接注入
this.strictInsertFill(metaObject, "createTime",
LocalDateTime.class, LocalDateTime.now());
}
}@TableField 負(fù)責(zé)標(biāo)記,Spring 負(fù)責(zé)注入,兩者解耦,符合單一職責(zé)。
8. 總結(jié):一張腦圖記住 @TableField
@TableField ├─ value 映射列名 ├─ exist 是否持久化 ├─ select 是否參與查詢(xún) ├─ fill 自動(dòng)填充策略 ├─ update 自定義 set 片段 ├─ condition 動(dòng)態(tài)條件 ├─ typeHandler 類(lèi)型轉(zhuǎn)換 └─ keepGlobalFormat 保留全局格式
9. 一鍵復(fù)制即可跑的最小 Demo
GitHub:https://github.com/YOUR_NAME/mp-tablefield-demo
分支:feature/tablefield-demo
包含:加密、樂(lè)觀鎖、多租戶(hù)、自動(dòng)填充 4 大示例,Maven 一鍵啟動(dòng)。
10. 評(píng)論區(qū) FAQ 預(yù)覽(提前回答)
Q1:@TableField 和 @Column 有什么區(qū)別?
A:后者是 JPA 規(guī)范,只在 Hibernate 生效;前者是 MyBatis-Plus 專(zhuān)用,功能更強(qiáng)。
Q2:能否在 Kotlin data class 使用?
A:可以,但字段必須聲明為 var,否則無(wú)法填充。
Q3:性能會(huì)下降嗎?
A:解析結(jié)果緩存到 TableInfo,運(yùn)行期零反射,性能損耗 < 1%。
到此這篇關(guān)于一文講透一個(gè) SpringBoot 裝飾器 —— @TableField的文章就介紹到這了,更多相關(guān)SpringBoot 裝飾器@TableField內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java中的遠(yuǎn)程方法調(diào)用之RPC使用
本文介紹了RPC的基本概念、核心思想及其在分布式系統(tǒng)中的作用,重點(diǎn)講解了Java中的三種RPC實(shí)現(xiàn)方式:RMI、Hessian和Dubbo,分別從適用場(chǎng)景、核心特點(diǎn)等方面做了對(duì)比對(duì)比較,并并提供了其基本實(shí)現(xiàn)代碼示例,總結(jié)了各框架的優(yōu)缺點(diǎn),為實(shí)際開(kāi)發(fā)中選擇合適的技術(shù)棧提供了參考2026-05-05
關(guān)于logBack配置日志文件及編碼配置的問(wèn)題
這篇文章主要介紹了logBack配置日志文件及編碼配置的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07
jpa使用注解生成表時(shí)無(wú)外鍵問(wèn)題及解決
這篇文章主要介紹了jpa使用注解生成表時(shí)無(wú)外鍵問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06
IDEA設(shè)置Maven自動(dòng)編譯model的實(shí)現(xiàn)方法
本文主要介紹了IDEA設(shè)置Maven自動(dòng)編譯model的實(shí)現(xiàn)方法, maven結(jié)構(gòu)的項(xiàng)目,我們?cè)诿看涡薷拇a后都會(huì)需要手動(dòng)編譯,本文就可以解決這個(gè)問(wèn)題,感興趣的可以了解一下2023-08-08
Java數(shù)據(jù)結(jié)構(gòu)中的HashMap和HashSet詳解
HashMap和HashSet都是存儲(chǔ)在哈希桶之中,通過(guò)本文我們可以先了解一些哈希桶是什么,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧2023-10-10

