MyBatis Plus 中 update_time 字段自動(dòng)填充失效的原因分析及解決方案(最新整理)
前言
在使用 MyBatis Plus 時(shí),通常我們會(huì)在數(shù)據(jù)庫(kù)表中設(shè)置 create_time
和 update_time
兩個(gè)字段,借助 MyBatis Plus 的 自動(dòng)填充功能 來(lái)維護(hù)這些時(shí)間字段。
但是,有時(shí)候你可能會(huì)遇到 update_time
字段未自動(dòng)更新的情況,哪怕代碼中已經(jīng)配置了 MetaObjectHandler
。本文將針對(duì)這一問(wèn)題,分析可能的原因,并提供詳細(xì)的解決方案。
一、問(wèn)題現(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ù)庫(kù)中的
update_time
字段未更新 - 沒(méi)有報(bào)錯(cuò),但
updateTime
依然是舊值 updateBy
可能也未更新
接下來(lái)我們來(lái)分析可能的原因。
二、原因分析
1. 使用了 strictInsertFill/strictUpdateFill
導(dǎo)致更新失效
原因:
strictInsertFill/strictUpdateFill
主要用于插入數(shù)據(jù)時(shí)的自動(dòng)填充。即使在 updateFill()
中使用它,也不會(huì)生效。
原理解釋?zhuān)?/strong>
strictInsertFill/strictUpdateFill
的作用是 如果字段已有值則不會(huì)覆蓋,而在更新場(chǎng)景中,一般實(shí)體對(duì)象中 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); }
原因分析補(bǔ)充:
strictInsertFill/strictUpdateFill
→ 插入/更新數(shù)據(jù)時(shí)填充,不適用于更新場(chǎng)景。setFieldValByName
→ 更新數(shù)據(jù)時(shí)直接覆蓋字段值,即使原值存在。
2. 實(shí)體類(lèi)注解配置錯(cuò)誤
原因:
實(shí)體類(lèi)中的字段沒(méi)有正確標(biāo)注 @TableField(fill = FieldFill.INSERT_UPDATE)
,導(dǎo)致自動(dòng)填充機(jī)制無(wú)法生效。
解決方案:
在實(shí)體類(lèi)中正確設(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
:用于插入和更新時(shí)自動(dòng)填充。- 如果沒(méi)有加上這個(gè)注解,MyBatis Plus 不會(huì)執(zhí)行自動(dòng)填充邏輯。
3. MetaObjectHandler
未生效
原因:
MetaObjectHandler
需要被 Spring 管理。如果沒(méi)有加上 @Component
注解或沒(méi)有被掃描到,自動(dòng)填充方法不會(huì)執(zhí)行。
解決方案:
確保 FieldAutoFillHandler
類(lèi)上有 @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); } }
注意:
如果項(xiàng)目中有多個(gè) MetaObjectHandler
,需要確保不會(huì)有沖突。
4. 使用自定義 SQL 導(dǎo)致自動(dòng)填充失效
原因:
如果你在 Mapper.xml
中自定義了 update
語(yǔ)句,那么 MyBatis Plus 不會(huì)觸發(fā)自動(dòng)填充邏輯。
解決方案:
方法 1:在 XML 中手動(dòng)設(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 會(huì)自動(dòng)觸發(fā)填充:
User user = userMapper.selectById(1L); user.setName("李四"); userMapper.updateById(user);
5. 字段類(lèi)型不匹配
原因:
數(shù)據(jù)庫(kù)中 update_time
的數(shù)據(jù)類(lèi)型與 Java 實(shí)體類(lèi)的類(lèi)型不匹配,導(dǎo)致填充失敗。
解決方案:
確保數(shù)據(jù)庫(kù)字段類(lèi)型和實(shí)體類(lèi)一致:
ALTER TABLE user MODIFY update_time TIMESTAMP NULL DEFAULT NULL;
private LocalDateTime updateTime;
注意:
- 使用
LocalDateTime
處理時(shí)間字段是最佳實(shí)踐。 - 如果數(shù)據(jù)庫(kù)字段為
datetime
或timestamp
,不要使用String
類(lèi)型。
三、總結(jié):常見(jiàn)原因與解決方法對(duì)照表
原因 | 現(xiàn)象 | 解決方法 |
---|---|---|
使用了 strictInsertFill | update_time 未更新 | 使用 setFieldValByName 替代 |
實(shí)體類(lèi)注解錯(cuò)誤 | 自動(dòng)填充無(wú)效 | 確保字段上加了 @TableField(fill = FieldFill.INSERT_UPDATE) |
MetaObjectHandler 未生效 | updateFill() 不執(zhí)行 | 確保加上 @Component 注解 |
使用自定義 SQL 覆蓋了默認(rèn)方法 | 填充邏輯未觸發(fā) | 使用 BaseMapper.updateById() 或在 SQL 中手動(dòng)填充 |
數(shù)據(jù)類(lèi)型不匹配 | 字段更新失敗 | 數(shù)據(jù)庫(kù)字段使用 timestamp 且實(shí)體類(lèi)使用 LocalDateTime |
四、推薦寫(xiě)法
最終推薦的 updateFill()
寫(xiě)法如下:
@Override public void updateFill(MetaObject metaObject) { log.info("執(zhí)行更新填充..."); this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject); this.setFieldValByName("updateBy", userId, metaObject); }
通過(guò)這種方式,確保 update_time
字段在更新時(shí)自動(dòng)更新,同時(shí)避免了不必要的填充失效問(wèn)題。
到此這篇關(guān)于MyBatis Plus 中 update_time 字段自動(dòng)填充失效的原因分析及解決方案(最新整理)的文章就介紹到這了,更多相關(guān)MyBatis Plus update_time 自動(dòng)填充失效內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring三級(jí)緩存解決循環(huán)依賴(lài)
本文主要介紹了Spring三級(jí)緩存解決循環(huán)依賴(lài),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12Java設(shè)計(jì)模式UML之類(lèi)圖精解
在UML類(lèi)圖中,類(lèi)使用包含類(lèi)名、屬性(field) 和方法(method) 且?guī)в蟹指罹€(xiàn)的矩形來(lái)表示,比如下圖表示一個(gè)Employee類(lèi),它包含name,age和email這3個(gè)屬性,以及modifyInfo()方法2022-02-02淺談java 單例模式DCL的缺陷及單例的正確寫(xiě)法
這篇文章主要介紹了淺談java 單例模式DCL的缺陷及單例的正確寫(xiě)法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09spring自定義注解實(shí)現(xiàn)攔截器的實(shí)現(xiàn)方法
本篇文章主要介紹了spring自定義注解實(shí)現(xiàn)攔截器的實(shí)現(xiàn)方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-08-08java private關(guān)鍵字用法實(shí)例
這篇文章主要介紹了java private關(guān)鍵字用法實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10Springboot處理跨域的實(shí)現(xiàn)方式(附Demo)
這篇文章主要介紹了Springboot處理跨域的實(shí)現(xiàn)方式(附Demo),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-04-04