大家好,我是小米,一個寫代碼也寫故事的31歲程序員。

上週五晚上,我在工位上加班修 Bug,手裏那杯咖啡都涼透了。原因嘛——老闆的一句話:“小米,你這表記錄誰創建的、什麼時候改的,怎麼都沒寫?”我一臉懵:“啊?這不是數據庫自帶的嗎?”老闆笑了笑,“你去查查 JPA Audit。”

就這樣,我打開電腦,走上了一條“審計字段自動填充”的覺醒之路。

那些年我們手動維護的時間戳

還記得剛入行那會兒,我寫的每個實體類都像這樣:

別再手動 set 時間了,JPA 一行註解全幫你搞定!_字段

每次插入數據,我要在 Service 裏手動加:

別再手動 set 時間了,JPA 一行註解全幫你搞定!_JPA_02

每次修改,又要寫:

別再手動 set 時間了,JPA 一行註解全幫你搞定!_數據庫_03

那時候覺得很自然,但後來項目一多,幾十個表、幾百個接口,這種重複代碼簡直要命。更慘的是——忘了寫!測試一改表數據,時間沒更新,歷史數據都亂套。於是我暗暗發誓:“有朝一日,一定要讓這些字段自動更新!”

直到那天,JPA 的 @CreatedDate 和 @LastModifiedDate 出現在我的視野中,像是照進加班狗世界的一束光。

JPA Audit:讓時間自動生長的魔法

Spring Data JPA 提供了一個非常優雅的方案:Auditing(審計)機制。簡單來説,就是自動幫你記錄實體的創建時間、修改時間、創建人、修改人。

其中,最常用的兩個註解就是:

  • @CreatedDate —— 自動記錄創建時間。
  • @LastModifiedDate —— 自動記錄最後修改時間。

是不是一看名字就懂了?沒錯,真正的懶人神器。

動手開整:三步啓用審計魔法

第一步:在配置類上開啓審計功能

在任意一個配置類或啓動類上加上這行註解:

@EnableJpaAuditing

這句話的意思很簡單:告訴 Spring,“以後幫我盯着數據庫記錄的變化,誰新建、誰修改都記下來!”

第二步:在實體類上聲明審計監聽

在你的實體類上加個監聽器,讓 Spring 知道要“監聽”它的變化。

@EntityListeners(AuditingEntityListener.class)

這一步很關鍵,沒有它,Spring 不知道你要被審計。

第三步:加上註解就完事了

別再手動 set 時間了,JPA 一行註解全幫你搞定!_JPA_04

然後呢?沒了。真的沒了!你再執行一次插入或更新,時間就會自動寫入數據庫,不用再管!

原理淺析:Spring 到底幹了啥?

有些同學可能會好奇:“小米,它到底是怎麼知道我在新增還是修改呢?”

其實,Auditing 的底層機制是基於 實體監聽器(Entity Listener) 的。

當你在實體上加上 @EntityListeners(AuditingEntityListener.class) 時,Spring 會在執行 save() 前後攔截生命週期事件(比如 @PrePersist、@PreUpdate),在插入前自動設置 @CreatedDate 字段,在更新前自動更新 @LastModifiedDate 字段。

這就像數據庫觸發器一樣,但實現更輕量、更優雅,還能配合 @CreatedBy、@LastModifiedBy 記錄操作人。

實戰演練:一個例子走天下

我當時在項目裏這樣寫的:

別再手動 set 時間了,JPA 一行註解全幫你搞定!_數據庫_05

然後我在啓動類上加上:

別再手動 set 時間了,JPA 一行註解全幫你搞定!_字段_06

當我執行:

別再手動 set 時間了,JPA 一行註解全幫你搞定!_字段_07

數據庫裏自動生成了時間戳!

別再手動 set 時間了,JPA 一行註解全幫你搞定!_字段_08

過幾分鐘,我再修改這個用户名字,再執行一次 save,發現 update_time 自動變成最新的時間,而 create_time 完好無損。那一刻我真心感嘆:Spring Data JPA 太懂程序員了!

順便説下時間精度的小坑

很多人第一次用時會踩一個坑:數據庫時間沒自動更新。

別慌,常見原因就兩個:

  1. 沒加 @EnableJpaAuditing:這是整個機制的總開關,不加它所有註解都白搭。
  2. 字段類型不對:推薦用 LocalDateTime,如果你用 Date 或 Instant,要確保配置了合適的轉換器。

另外,@Column(updatable = false) 千萬別亂加在 @LastModifiedDate 上,否則它更新不了!

進階玩法:記錄創建人和修改人

除了時間,JPA 還能幫你自動記錄“誰”創建了這條數據。

新增兩個註解即可:

  • @CreatedBy
  • @LastModifiedBy

比如:

別再手動 set 時間了,JPA 一行註解全幫你搞定!_JPA_09

但要注意:這兩個字段依賴於 AuditorAware 接口,你需要自己告訴 JPA 當前是誰在操作:

別再手動 set 時間了,JPA 一行註解全幫你搞定!_字段_10

在真實項目中,你可以從登錄上下文中取當前用户名。這樣,每次插入或更新數據,createUser 和 updateUser 就會自動帶上值。

再説點小故事

我把這套審計機制加到項目後,老闆第一次審查代碼時問:“你這次寫的日誌表不錯啊,時間記錄得很清楚。”

我笑着回:“我沒寫,Spring 幫我寫的。”

他愣了兩秒,然後豎起大拇指:“幹得漂亮。”

從那以後,我再也不用擔心忘記更新時間、創建時間。甚至在代碼評審時,同事看到註解風格的審計方案,都感嘆一句:“這才是優雅的後端。”

總結:三行註解,讓代碼更乾淨

用一句話總結今天的主角:

@CreatedDate 和 @LastModifiedDate,不僅讓你少寫代碼,還能讓系統更可靠、更可追溯。

它們背後體現的是“讓框架幫你做重複的事,讓開發者專注在業務邏輯”的理念。

所以,下一次當你新建實體類時,不妨給它加上這些註解。讓時間自動生長,讓代碼更有生命力。

END

我是小米,一個喜歡分享技術的31歲程序員。如果你喜歡我的文章,歡迎關注我的微信公眾號“軟件求生”,獲取更多技術乾貨!

我們下次見~