MyBatis Plus 中 update_time 字段自動填充失效的原因分析及解決方案(最新整理)
前言
在使用 MyBatis Plus 時,通常我們會在數(shù)據(jù)庫表中設(shè)置 create_time 和 update_time 兩個字段,借助 MyBatis Plus 的 自動填充功能 來維護(hù)這些時間字段。
但是,有時候你可能會遇到 update_time 字段未自動更新的情況,哪怕代碼中已經(jīng)配置了 MetaObjectHandler。本文將針對這一問題,分析可能的原因,并提供詳細(xì)的解決方案。
一、問題現(xiàn)象
假設(shè)我們有如下的 updateFill() 方法:
@Override
public void updateFill(MetaObject metaObject) {
log.info("執(zhí)行更新填充...");
this.strictInsertFill(metaObject, "updateTime", Timestamp.class, Timestamp.valueOf(LocalDateTime.now()));
this.strictInsertFill(metaObject, "updateBy", BigInteger.class, userId);
}但是執(zhí)行更新操作后:
- 數(shù)據(jù)庫中的
update_time字段未更新 - 沒有報錯,但
updateTime依然是舊值 updateBy可能也未更新
接下來我們來分析可能的原因。
二、原因分析
1. 使用了 strictInsertFill/strictUpdateFill 導(dǎo)致更新失效
原因:
strictInsertFill/strictUpdateFill 主要用于插入數(shù)據(jù)時的自動填充。即使在 updateFill() 中使用它,也不會生效。
原理解釋:
strictInsertFill/strictUpdateFill 的作用是 如果字段已有值則不會覆蓋,而在更新場景中,一般實體對象中 update_time 已有值。
解決方案:
將 strictInsertFill/strictUpdateFill 替換為 setFieldValByName:
@Override
public void updateFill(MetaObject metaObject) {
log.info("start update fill ....");
this.setFieldValByName("updateTime", Timestamp.valueOf(LocalDateTime.now()), metaObject);
this.setFieldValByName("updateBy", userId, metaObject);
}原因分析補充:
strictInsertFill/strictUpdateFill→ 插入/更新數(shù)據(jù)時填充,不適用于更新場景。setFieldValByName→ 更新數(shù)據(jù)時直接覆蓋字段值,即使原值存在。
2. 實體類注解配置錯誤
原因:
實體類中的字段沒有正確標(biāo)注 @TableField(fill = FieldFill.INSERT_UPDATE),導(dǎo)致自動填充機(jī)制無法生效。
解決方案:
在實體類中正確設(shè)置注解:
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class User {
private Long id;
private String name;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private BigInteger updateBy;
}注意:
FieldFill.INSERT_UPDATE:用于插入和更新時自動填充。- 如果沒有加上這個注解,MyBatis Plus 不會執(zhí)行自動填充邏輯。
3. MetaObjectHandler 未生效
原因:
MetaObjectHandler 需要被 Spring 管理。如果沒有加上 @Component 注解或沒有被掃描到,自動填充方法不會執(zhí)行。
解決方案:
確保 FieldAutoFillHandler 類上有 @Component 注解:
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class FieldAutoFillHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
log.info("執(zhí)行插入填充...");
this.setFieldValByName("createTime", LocalDateTime.now(), metaObject);
this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
log.info("執(zhí)行更新填充...");
this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
}
}注意:
如果項目中有多個 MetaObjectHandler,需要確保不會有沖突。
4. 使用自定義 SQL 導(dǎo)致自動填充失效
原因:
如果你在 Mapper.xml 中自定義了 update 語句,那么 MyBatis Plus 不會觸發(fā)自動填充邏輯。
解決方案:
方法 1:在 XML 中手動設(shè)置 update_time 字段:
<update id="updateUser" parameterType="com.example.entity.User">
UPDATE user
SET name = #{name},
update_time = NOW(),
update_by = #{updateBy}
WHERE id = #{id}
</update>方法 2:直接使用 BaseMapper 提供的 updateById() 等方法,MyBatis Plus 會自動觸發(fā)填充:
User user = userMapper.selectById(1L);
user.setName("李四");
userMapper.updateById(user);5. 字段類型不匹配
原因:
數(shù)據(jù)庫中 update_time 的數(shù)據(jù)類型與 Java 實體類的類型不匹配,導(dǎo)致填充失敗。
解決方案:
確保數(shù)據(jù)庫字段類型和實體類一致:
ALTER TABLE user MODIFY update_time TIMESTAMP NULL DEFAULT NULL;
private LocalDateTime updateTime;
注意:
- 使用
LocalDateTime處理時間字段是最佳實踐。 - 如果數(shù)據(jù)庫字段為
datetime或timestamp,不要使用String類型。
三、總結(jié):常見原因與解決方法對照表
| 原因 | 現(xiàn)象 | 解決方法 |
|---|---|---|
使用了 strictInsertFill | update_time 未更新 | 使用 setFieldValByName 替代 |
| 實體類注解錯誤 | 自動填充無效 | 確保字段上加了 @TableField(fill = FieldFill.INSERT_UPDATE) |
MetaObjectHandler 未生效 | updateFill() 不執(zhí)行 | 確保加上 @Component 注解 |
| 使用自定義 SQL 覆蓋了默認(rèn)方法 | 填充邏輯未觸發(fā) | 使用 BaseMapper.updateById() 或在 SQL 中手動填充 |
| 數(shù)據(jù)類型不匹配 | 字段更新失敗 | 數(shù)據(jù)庫字段使用 timestamp 且實體類使用 LocalDateTime |
四、推薦寫法
最終推薦的 updateFill() 寫法如下:
@Override
public void updateFill(MetaObject metaObject) {
log.info("執(zhí)行更新填充...");
this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
this.setFieldValByName("updateBy", userId, metaObject);
}通過這種方式,確保 update_time 字段在更新時自動更新,同時避免了不必要的填充失效問題。
到此這篇關(guān)于MyBatis Plus 中 update_time 字段自動填充失效的原因分析及解決方案(最新整理)的文章就介紹到這了,更多相關(guān)MyBatis Plus update_time 自動填充失效內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
spring自定義注解實現(xiàn)攔截器的實現(xiàn)方法
本篇文章主要介紹了spring自定義注解實現(xiàn)攔截器的實現(xiàn)方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-08-08
Springboot處理跨域的實現(xiàn)方式(附Demo)
這篇文章主要介紹了Springboot處理跨域的實現(xiàn)方式(附Demo),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-04-04

