MyBatis Plus實現(xiàn)時間字段自動填充的完整方案
前言
在日常開發(fā)中,我們經(jīng)常需要記錄數(shù)據(jù)的創(chuàng)建時間和更新時間。傳統(tǒng)的做法是在每次插入或更新操作時手動設(shè)置這些時間字段,這種方式不僅繁瑣,還容易遺漏。本文將介紹如何使用 MyBatis Plus 的自動填充功能來優(yōu)雅地解決這個問題。
解決目標(biāo)
- 創(chuàng)建記錄時自動設(shè)置
createTime和updateTime - 更新記錄時自動更新
updateTime,保持createTime不變 - 無需手動編寫時間設(shè)置代碼
- 統(tǒng)一的時間管理機制
技術(shù)棧
- 框架: Spring Boot + MyBatis Plus
- 數(shù)據(jù)庫: MySQL
- 實體管理: JPA 注解 + MyBatis Plus 注解
實現(xiàn)步驟
1. 實體類注解配置
首先在實體類的時間字段上添加 MyBatis Plus 的自動填充注解:
/**
* 郵箱服務(wù)器實體類
*/
@Entity
@Table(name = "tbl_email_server")
public class EmailServer extends BaseEntity {
// 其他字段...
/** 創(chuàng)建時間 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@TableField(fill = FieldFill.INSERT)
private Date createTime;
/** 更新時間 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
// getter 和 setter 方法...
}
注解說明:
@TableField(fill = FieldFill.INSERT): 僅在插入操作時自動填充@TableField(fill = FieldFill.INSERT_UPDATE): 在插入和更新操作時都自動填充@JsonFormat: 指定 JSON 序列化時的日期格式
2. 創(chuàng)建元數(shù)據(jù)處理器
創(chuàng)建自定義的元數(shù)據(jù)處理器來實現(xiàn)具體的填充邏輯:
package com.ruoyi.framework.config;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* MyBatis Plus 字段自動填充處理器
*
* @author ruoyi
*/
@Component
public class MyBatisMetaObjectHandler implements MetaObjectHandler {
/**
* 插入時的填充策略
*/
@Override
public void insertFill(MetaObject metaObject) {
Date now = new Date();
// 插入時同時填充創(chuàng)建時間和更新時間
this.strictInsertFill(metaObject, "createTime", Date.class, now);
this.strictInsertFill(metaObject, "updateTime", Date.class, now);
}
/**
* 更新時的填充策略
*/
@Override
public void updateFill(MetaObject metaObject) {
// 更新時僅填充更新時間
this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());
}
}
核心方法說明:
insertFill(): 處理插入操作的字段填充updateFill(): 處理更新操作的字段填充strictInsertFill(): 嚴(yán)格插入填充,只有當(dāng)字段值為 null 時才填充strictUpdateFill(): 嚴(yán)格更新填充,只有當(dāng)字段值為 null 時才填充
3. 服務(wù)層代碼優(yōu)化
移除原本手動設(shè)置時間的代碼:
修改前:
@Override
public int insertEmailServer(EmailServer emailServer) {
// 手動設(shè)置時間字段
emailServer.setCreateBy(SecurityUtils.getUsername());
emailServer.setCreateTime(new Date()); // ? 需要移除
emailServer.setUpdateTime(new Date()); // ? 需要移除
return emailServerMapper.insertEmailServer(emailServer);
}
@Override
public int updateEmailServer(EmailServer emailServer) {
emailServer.setUpdateBy(SecurityUtils.getUsername());
emailServer.setUpdateTime(new Date()); // ? 需要移除
return emailServerMapper.updateEmailServer(emailServer);
}
修改后:
@Override
public int insertEmailServer(EmailServer emailServer) {
// 只設(shè)置創(chuàng)建者,時間字段由 MyBatis Plus 自動填充
emailServer.setCreateBy(SecurityUtils.getUsername());
return emailServerMapper.insertEmailServer(emailServer);
}
@Override
public int updateEmailServer(EmailServer emailServer) {
// 只設(shè)置更新者,更新時間由 MyBatis Plus 自動填充
emailServer.setUpdateBy(SecurityUtils.getUsername());
return emailServerMapper.updateEmailServer(emailServer);
}
填充機制詳解
創(chuàng)建記錄時的填充過程
// 執(zhí)行插入操作
EmailServer emailServer = new EmailServer();
emailServer.setServerName("SMTP服務(wù)器");
// ... 設(shè)置其他業(yè)務(wù)字段
// 調(diào)用 insertEmailServer 時,MyBatis Plus 會:
// 1. 觸發(fā) insertFill 方法
// 2. createTime = 2024-01-15 10:30:25
// 3. updateTime = 2024-01-15 10:30:25 (與創(chuàng)建時間相同)
更新記錄時的填充過程
// 執(zhí)行更新操作
EmailServer emailServer = new EmailServer();
emailServer.setServerId(1L);
emailServer.setServerName("新的服務(wù)器名稱");
// ... 修改其他業(yè)務(wù)字段
// 調(diào)用 updateEmailServer 時,MyBatis Plus 會:
// 1. 觸發(fā) updateFill 方法
// 2. createTime = 保持原值不變
// 3. updateTime = 2024-01-15 14:25:30 (更新為當(dāng)前時間)
數(shù)據(jù)庫建議配置
雖然使用了注解自動填充,但建議在數(shù)據(jù)庫層面也設(shè)置默認(rèn)值作為雙重保障:
-- 為時間字段添加默認(rèn)值 ALTER TABLE tbl_email_server MODIFY COLUMN create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間'; ALTER TABLE tbl_email_server MODIFY COLUMN update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時間';
前后對比
| 對比項 | 手動設(shè)置方式 | 自動填充方式 |
|---|---|---|
| 代碼量 | 每個方法都需要設(shè)置 | 一次配置,全局生效 |
| 維護性 | 容易遺漏,難以統(tǒng)一 | 統(tǒng)一管理,不易出錯 |
| 一致性 | 依賴開發(fā)者自覺性 | 自動保證一致性 |
| 性能 | 無額外性能消耗 | 微小的反射開銷 |
進階擴展
1. 支持更多字段類型
@Override
public void insertFill(MetaObject metaObject) {
Date now = new Date();
// 支持 Date 類型
this.strictInsertFill(metaObject, "createTime", Date.class, now);
this.strictInsertFill(metaObject, "updateTime", Date.class, now);
// 支持 LocalDateTime 類型
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
// 支持時間戳
this.strictInsertFill(metaObject, "createTime", Long.class, System.currentTimeMillis());
}
2. 添加創(chuàng)建者和更新者自動填充
@Override
public void insertFill(MetaObject metaObject) {
Date now = new Date();
String currentUser = getCurrentUser(); // 獲取當(dāng)前用戶
// 時間字段填充
this.strictInsertFill(metaObject, "createTime", Date.class, now);
this.strictInsertFill(metaObject, "updateTime", Date.class, now);
// 用戶字段填充
this.strictInsertFill(metaObject, "createBy", String.class, currentUser);
this.strictInsertFill(metaObject, "updateBy", String.class, currentUser);
}
@Override
public void updateFill(MetaObject metaObject) {
String currentUser = getCurrentUser();
this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());
this.strictUpdateFill(metaObject, "updateBy", String.class, currentUser);
}
private String getCurrentUser() {
try {
return SecurityUtils.getUsername();
} catch (Exception e) {
return "system"; // 默認(rèn)用戶
}
}
常見問題與解決方案
1. 字段沒有自動填充
可能原因:
- 實體類字段名與數(shù)據(jù)庫列名不匹配
- 忘記添加
@TableField注解 - MetaObjectHandler 沒有被 Spring 管理
解決方案:
// 確保字段名正確映射
@TableField(value = "create_time", fill = FieldFill.INSERT)
private Date createTime;
// 確保處理器被 Spring 管理
@Component // 必須添加此注解
public class MyBatisMetaObjectHandler implements MetaObjectHandler {
// ...
}
2. 更新操作時創(chuàng)建時間被意外修改
解決方案:
// 使用 FieldFill.INSERT 而不是 INSERT_UPDATE @TableField(fill = FieldFill.INSERT) // ? 正確 private Date createTime; @TableField(fill = FieldFill.INSERT_UPDATE) // ? 正確 private Date updateTime;
3. JSON 序列化時間格式問題
解決方案:
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @TableField(fill = FieldFill.INSERT_UPDATE) private Date updateTime;
總結(jié)
MyBatis Plus 的自動填充功能為我們提供了一個優(yōu)雅的解決方案來管理時間字段:
優(yōu)勢
- 自動化: 無需手動編寫重復(fù)的時間設(shè)置代碼
- 統(tǒng)一性: 全局統(tǒng)一的時間填充策略
- 可靠性: 避免了人為遺漏設(shè)置時間的問題
- 擴展性: 可以輕松擴展到其他字段的自動填充
核心實現(xiàn)
- 在實體類時間字段添加
@TableField注解 - 創(chuàng)建實現(xiàn)
MetaObjectHandler接口的處理器 - 在處理器中實現(xiàn)
insertFill和updateFill方法 - 移除服務(wù)層中的手動時間設(shè)置代碼
這種方案不僅提升了開發(fā)效率,還增強了代碼的可維護性和一致性。在實際項目中,建議結(jié)合數(shù)據(jù)庫默認(rèn)值設(shè)置,形成雙重保障機制。
以上就是MyBatis Plus實現(xiàn)時間字段自動填充的完整方案的詳細(xì)內(nèi)容,更多關(guān)于MyBatis Plus時間字段自動填充的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java中Hashtable和HashMap的區(qū)別分析
java中Hashtable和HashMap的區(qū)別分析,需要的朋友可以參考一下2013-04-04
SpringBoot配置默認(rèn)HikariCP數(shù)據(jù)源
咱們開發(fā)項目的過程中用到很多的開源數(shù)據(jù)庫鏈接池,比如druid、c3p0、BoneCP等等,本文主要介紹了SpringBoot配置默認(rèn)HikariCP數(shù)據(jù)源,具有一定的參考價值,感興趣的可以了解一下2023-11-11

