国产av一二三区|日本不卡动作网站|黄色天天久久影片|99草成人免费在线视频|AV三级片成人电影在线|成年人aV不卡免费播放|日韩无码成人一级片视频|人人看人人玩开心色AV|人妻系列在线观看|亚洲av无码一区二区三区在线播放

網(wǎng)易首頁 > 網(wǎng)易號 > 正文 申請入駐

解放雙手:SpringBoot 公共字段自動填充 6 種神技,開發(fā)效率飆升!

0
分享至

Java精選面試題(微信小程序):5000+道面試題和選擇題,真實(shí)面經(jīng),簡歷模版,包含Java基礎(chǔ)、并發(fā)、JVM、線程、MQ系列、Redis、Spring系列、Elasticsearch、Docker、K8s、Flink、Spark、架構(gòu)設(shè)計、大廠真題等,在線隨時刷題!

在開發(fā)外賣系統(tǒng)訂單模塊時,我發(fā)現(xiàn)每個實(shí)體類都包含create_time、update_by等重復(fù)字段。手動維護(hù)這些字段不僅效率低下,還容易出錯。

本文將分享一套經(jīng)過生產(chǎn)驗證的自動化方案,涵蓋MyBatis-Plus、AOP、JWT等六種核心策略,助你徹底擺脫公共字段維護(hù)的煩惱。

一、痛點(diǎn)分析:公共字段維護(hù)的三大困境 1.1 典型問題場景

// 訂單創(chuàng)建邏輯 public void createOrder(OrderDTO dto) {     Order order = convertToEntity(dto);          // 手動設(shè)置公共字段     order.setCreateTime(LocalDateTime.now());     order.setUpdateTime(LocalDateTime.now());     order.setCreateUser(getCurrentUser());     order.setUpdateUser(getCurrentUser());          orderMapper.insert(order); } // 訂單更新邏輯  public void updateOrder(OrderDTO dto) {     Order order = convertToEntity(dto);          // 重復(fù)設(shè)置邏輯     order.setUpdateTime(LocalDateTime.now());     order.setUpdateUser(getCurrentUser());          orderMapper.updateById(order); }

痛點(diǎn)總結(jié):

  • 代碼重復(fù)率高(每個Service方法都要設(shè)置)

  • 維護(hù)成本高(字段變更需修改多處)

  • 容易遺漏(特別是更新操作)

二、基礎(chǔ)方案:MyBatis-Plus自動填充 2.1 配置元對象處理器

@Slf4j @Component publicclass AutoFillHandler implements MetaObjectHandler {          // 插入時自動填充     @Override     public void insertFill(MetaObject metaObject) {         this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());         this.strictInsertFill(metaObject, "createUser", String.class, getCurrentUser());         this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());         this.strictUpdateFill(metaObject, "updateUser", String.class, getCurrentUser());     }     // 更新時自動填充     @Override     public void updateFill(MetaObject metaObject) {         this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());         this.strictUpdateFill(metaObject, "updateUser", String.class, getCurrentUser());     }          // 獲取當(dāng)前用戶(從安全上下文)     private String getCurrentUser() {         return Optional.ofNullable(SecurityContextHolder.getContext())                       .map(SecurityContext::getAuthentication)                       .map(Authentication::getName)                       .orElse("system");     } }
2.2 實(shí)體類注解配置

@Data publicclass BaseEntity {     @TableField(fill = FieldFill.INSERT)     private LocalDateTime createTime;          @TableField(fill = FieldFill.INSERT_UPDATE)     private LocalDateTime updateTime;          @TableField(fill = FieldFill.INSERT)     private String createUser;          @TableField(fill = FieldFill.INSERT_UPDATE)     private String updateUser; } // 訂單實(shí)體繼承基類 publicclass Order extends BaseEntity {     // 業(yè)務(wù)字段... }
三、進(jìn)階方案:AOP統(tǒng)一處理 3.1 自定義注解

@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface AutoFill {     OperationType value(); } public enum OperationType {     INSERT,     UPDATE }
3.2 切面實(shí)現(xiàn)

@Aspect @Component @Slf4j publicclass AutoFillAspect {          @Autowired     private ObjectMapper objectMapper;     @Around("@annotation(autoFill)")     public Object around(ProceedingJoinPoint pjp, AutoFill autoFill) throws Throwable {         Object[] args = pjp.getArgs();         for (Object arg : args) {             if (arg instanceof BaseEntity) {                 fillFields((BaseEntity) arg, autoFill.value());             }         }         return pjp.proceed(args);     }     private void fillFields(BaseEntity entity, OperationType type) {         String currentUser = getCurrentUser();         LocalDateTime now = LocalDateTime.now();                  if (type == OperationType.INSERT) {             entity.setCreateTime(now);             entity.setCreateUser(currentUser);         }         entity.setUpdateTime(now);         entity.setUpdateUser(currentUser);     }          // 獲取當(dāng)前用戶(支持多線程環(huán)境)     private String getCurrentUser() {         return Optional.ofNullable(RequestContextHolder.getRequestAttributes())                       .map(attrs -> (ServletRequestAttributes) attrs)                       .map(ServletRequestAttributes::getRequest)                       .map(req -> req.getHeader("X-User-Id"))                       .orElse("system");     } }
四、生產(chǎn)環(huán)境最佳實(shí)踐 4.1 多數(shù)據(jù)源適配

@Configuration publicclass DataSourceConfig {          @Bean     @ConfigurationProperties("spring.datasource.master")     public DataSource masterDataSource() {         return DataSourceBuilder.create().build();     }          @Bean     public MetaObjectHandler metaObjectHandler() {         returnnew MultiDataSourceAutoFillHandler();     } } publicclass MultiDataSourceAutoFillHandler extends MetaObjectHandler {     // 根據(jù)當(dāng)前數(shù)據(jù)源動態(tài)處理 }
4.2 分布式ID生成

public class SnowflakeIdGenerator {     // 實(shí)現(xiàn)分布式ID生成 } // 在自動填充中集成 @Override public void insertFill(MetaObject metaObject) {     this.strictInsertFill(metaObject, "id", String.class,          idGenerator.nextId()); }
五、避坑指南:五大常見問題 5.1 空指針異常防護(hù)

// 使用Optional處理可能為空的情況 private String safeGetUser() {     return Optional.ofNullable(SecurityContextHolder.getContext())                  .map(SecurityContext::getAuthentication)                  .map(Authentication::getPrincipal)                  .map(principal -> {                      if (principal instanceof UserDetails) {                          return ((UserDetails) principal).getUsername();                      }                      return principal.toString();                  })                  .orElse("system"); }
5.2 字段覆蓋問題

// 在實(shí)體類中使用@TableField策略 @TableField(fill = FieldFill.INSERT, updateStrategy = FieldStrategy.NEVER) private String createUser;
六、性能優(yōu)化方案 6.1 緩存當(dāng)前用戶信息

public class UserContextHolder {     privatestaticfinal ThreadLocal userHolder =  new ThreadLocal<>();          public static void setUser(String user) {         userHolder.set(user);     }          public static String getUser() {         return userHolder.get();     }          public static void clear() {         userHolder.remove();     } } // 在攔截器中設(shè)置 publicclass UserInterceptor implements HandlerInterceptor {     @Override     public boolean preHandle(HttpServletRequest request,                              HttpServletResponse response,                              Object handler) {         UserContextHolder.setUser(request.getHeader("X-User-Id"));         returntrue;     } }
6.2 批量操作優(yōu)化

@Transactional public void batchInsert(List orders)  {     // 提前獲取公共字段值     String user = getCurrentUser();     LocalDateTime now = LocalDateTime.now();          orders.forEach(order -> {         order.setCreateTime(now);         order.setCreateUser(user);         order.setUpdateTime(now);         order.setUpdateUser(user);     });          orderMapper.batchInsert(orders); }
七、監(jiān)控與審計 7.1 審計日志集成

@EntityListeners(AuditingEntityListener.class) public class BaseEntity {     @CreatedBy     private String createUser;          @LastModifiedBy     private String updateUser;          @CreatedDate     private LocalDateTime createTime;          @LastModifiedDate     private LocalDateTime updateTime; }
7.2 操作日志追蹤

@Aspect @Component public class OperationLogAspect {          @AfterReturning("@annotation(autoFill)")     public void logOperation(AutoFill autoFill) {         LogEntry log = new LogEntry();         log.setOperator(getCurrentUser());         log.setOperationType(autoFill.value().name());         logService.save(log);     } }

結(jié)語:通過本文的六種方案組合使用,我們在生產(chǎn)環(huán)境中實(shí)現(xiàn)了:

  • 公共字段維護(hù)代碼量減少90%

  • 相關(guān)Bug率下降75%

  • 新功能開發(fā)效率提升40%

最佳實(shí)踐清單:

  • 基礎(chǔ)字段使用MyBatis-Plus自動填充

  • 復(fù)雜場景結(jié)合AOP處理

  • 分布式環(huán)境集成唯一ID生成

  • 重要操作添加審計日志

  • 定期檢查字段填充策略

未來展望:隨著Spring Data JPA的演進(jìn),未來可以探索與Reactive編程的結(jié)合,實(shí)現(xiàn)全鏈路的非阻塞式自動填充。

來源:https://juejin.cn/post/7494549596258189362

公眾號“Java精選”所發(fā)表內(nèi)容注明來源的,版權(quán)歸原出處所有(無法查證版權(quán)的或者未注明出處的均來自網(wǎng)絡(luò),系轉(zhuǎn)載,轉(zhuǎn)載的目的在于傳遞更多信息,版權(quán)屬于原作者。如有侵權(quán),請聯(lián)系,筆者會第一時間刪除處理!

最近有很多人問,有沒有讀者交流群!加入方式很簡單,公眾號Java精選,回復(fù)“加群”,即可入群!

文章有幫助的話,點(diǎn)在看,轉(zhuǎn)發(fā)吧!

特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺“網(wǎng)易號”用戶上傳并發(fā)布,本平臺僅提供信息存儲服務(wù)。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相關(guān)推薦
熱點(diǎn)推薦
被曝生下畸形兒傳聞僅1月,闞清子官宣喜訊,連發(fā)三文表明態(tài)度

被曝生下畸形兒傳聞僅1月,闞清子官宣喜訊,連發(fā)三文表明態(tài)度

一口娛樂
2026-01-29 09:31:09
已確認(rèn),浙江有大到暴雪!今晚變天

已確認(rèn),浙江有大到暴雪!今晚變天

魯中晨報
2026-01-29 13:39:09
不敢置信!女子十二樂坊成員直播養(yǎng)不活自己,一晚上打賞不到3000

不敢置信!女子十二樂坊成員直播養(yǎng)不活自己,一晚上打賞不到3000

云中浮生
2026-01-24 21:37:46
奇葩!35歲女子4年不回家,母親來探望卻被懟,女子:就當(dāng)我死了

奇葩!35歲女子4年不回家,母親來探望卻被懟,女子:就當(dāng)我死了

娛樂帝皇丸
2026-01-28 15:18:51
16歲武漢男生凌晨離家,失聯(lián)超70小時, 父親:未帶手機(jī)現(xiàn)金,最后出現(xiàn)在橋上不見蹤跡

16歲武漢男生凌晨離家,失聯(lián)超70小時, 父親:未帶手機(jī)現(xiàn)金,最后出現(xiàn)在橋上不見蹤跡

大風(fēng)新聞
2026-01-29 13:53:22
人民日報怒批!炫富、偷稅749萬、跑國外,現(xiàn)又來“割內(nèi)地韭菜”

人民日報怒批!炫富、偷稅749萬、跑國外,現(xiàn)又來“割內(nèi)地韭菜”

小熊侃史
2026-01-18 07:20:09
港股地產(chǎn)股大漲,融創(chuàng)中國漲超30%

港股地產(chǎn)股大漲,融創(chuàng)中國漲超30%

每日經(jīng)濟(jì)新聞
2026-01-29 11:39:06
外交部:繼續(xù)深化國際執(zhí)法合作 加大力度打擊網(wǎng)賭電詐

外交部:繼續(xù)深化國際執(zhí)法合作 加大力度打擊網(wǎng)賭電詐

財聯(lián)社
2026-01-29 15:26:24
尼帕病毒來勢洶洶,建議:每家最好備6樣?xùn)|西,關(guān)鍵時刻能救命呢

尼帕病毒來勢洶洶,建議:每家最好備6樣?xùn)|西,關(guān)鍵時刻能救命呢

現(xiàn)代小青青慕慕
2026-01-28 08:59:53
阿富汗的鍋,拜登不背!

阿富汗的鍋,拜登不背!

山河路口
2026-01-28 23:12:39
心理學(xué)上有一個詞叫:梅拉賓法則(搞好人際關(guān)系最好的辦法)

心理學(xué)上有一個詞叫:梅拉賓法則(搞好人際關(guān)系最好的辦法)

經(jīng)濟(jì)觀察報
2025-09-01 10:06:25
1971年,劉思齊蒙冤入獄后向毛主席求助,毛澤東作出:娃娃們無罪

1971年,劉思齊蒙冤入獄后向毛主席求助,毛澤東作出:娃娃們無罪

史海孤雁
2026-01-27 18:02:17
瞞不住了!美媒:美軍高官已進(jìn)臺島指揮導(dǎo)彈戰(zhàn),戰(zhàn)時先炸福建沿海

瞞不住了!美媒:美軍高官已進(jìn)臺島指揮導(dǎo)彈戰(zhàn),戰(zhàn)時先炸福建沿海

史智文道
2026-01-29 16:14:14
要打就打痛!中國手段已升級,日本:中方不批準(zhǔn)駐重慶總領(lǐng)事任命

要打就打痛!中國手段已升級,日本:中方不批準(zhǔn)駐重慶總領(lǐng)事任命

通文知史
2026-01-28 14:30:03
太頂了!明明什么都沒露,卻性感得要命!

太頂了!明明什么都沒露,卻性感得要命!

貴圈真亂
2025-12-20 12:02:06
最新傷勢情況曝光,德約科維奇直言:對辛納絕不舉白旗

最新傷勢情況曝光,德約科維奇直言:對辛納絕不舉白旗

體育妞世界
2026-01-29 12:38:11
起風(fēng)了!加拿大已改口,禁止與中國簽協(xié)定,65萬噸油菜籽白買了?

起風(fēng)了!加拿大已改口,禁止與中國簽協(xié)定,65萬噸油菜籽白買了?

墨印齋
2026-01-29 11:47:54
加快男性衰老的因素:喝酒僅第5,排在第1的,很多男性還沒發(fā)現(xiàn)!

加快男性衰老的因素:喝酒僅第5,排在第1的,很多男性還沒發(fā)現(xiàn)!

醫(yī)學(xué)科普匯
2026-01-27 10:41:31
中國人一年少買了10萬輛進(jìn)口寶馬

中國人一年少買了10萬輛進(jìn)口寶馬

第一財經(jīng)資訊
2026-01-29 10:34:13
1973年,毛主席問楊振寧:萬壽無疆科學(xué)嗎?楊振寧的回答,讓主席笑了

1973年,毛主席問楊振寧:萬壽無疆科學(xué)嗎?楊振寧的回答,讓主席笑了

寄史言志
2026-01-24 17:53:13
2026-01-29 17:15:00
Java精選
Java精選
一場永遠(yuǎn)也演不完的戲
1768文章數(shù) 3859關(guān)注度
往期回顧 全部

科技要聞

周亞輝的AI新賭局:國內(nèi)太卷 出海另起爐灶

頭條要聞

女大學(xué)生到東北游玩暈倒雪地凍傷 三根手指或面臨截肢

頭條要聞

女大學(xué)生到東北游玩暈倒雪地凍傷 三根手指或面臨截肢

體育要聞

詹姆斯哭了!騎士視頻致敬41歲超巨

娛樂要聞

張譯不再隱瞞!公開回應(yīng)退圈息影真相

財經(jīng)要聞

崔東樹:中國汽車未來年銷或達(dá)5000萬輛

汽車要聞

車長超5米還帶后輪轉(zhuǎn)向 比亞迪海豹08/海獅08將亮相

態(tài)度原創(chuàng)

數(shù)碼
健康
藝術(shù)
教育
親子

數(shù)碼要聞

這種電熱水袋國家早已禁售:別再用了

耳石癥分類型,癥狀大不同

藝術(shù)要聞

梵高全集(高清350張)震撼……

教育要聞

“國家課程落地吳江行動叢書”發(fā)布!聚焦課改前沿,共探育人新路!

親子要聞

一個現(xiàn)象:縣城里的孕婦越來越少了

無障礙瀏覽 進(jìn)入關(guān)懷版