解決mybatisplus MetaObjectHandler 失效的問題
一、什么是metaObjectHandler
MetaObjectHandler接口是mybatisPlus為我們提供的的一個擴(kuò)展接口,我們可以利用這個接口在我們插入或者更新數(shù)據(jù)的時候,為一些字段指定默認(rèn)值
使用方式如下:
1、在實(shí)體類上加入@TableField注解
@Getter @Setter public class AbstractBaseDO<T extends Model<T>> extends Model<T> implements Serializable { ? ? /** ? ? ?* 創(chuàng)建時間 新增時填充 ? ? ?*/ ? ? @TableField(fill = FieldFill.INSERT) ? ? private Date gmtCreate; ? ? /** ? ? ?* 修改時間 新增和更新時填充 ? ? ?*/ ? ? @TableField(fill = FieldFill.INSERT_UPDATE) ? ? private Date gmtModified; ? ? /** ? ? ?* 創(chuàng)建人ID 新增時更新 ? ? ?*/ ? ? @TableField(fill = FieldFill.INSERT) ? ? private Long creatorId; ? ? /** ? ? ?* 修改人ID 新增和更新時填充 ? ? ?*/ ? ? @TableField(fill = FieldFill.INSERT_UPDATE) ? ? private Long modifierId; ? ? /** ? ? ?* 邏輯刪除字段 新增和更新時填充 ? ? ?*/ ? ? @TableField(fill = FieldFill.INSERT_UPDATE) ? ? private Integer isDeleted; ? ? @Override ? ? public String toString() { ? ? ? ? return new ToStringBuilder(this) ? ? ? ? ? ? .append("gmtCreate", gmtCreate) ? ? ? ? ? ? .append("gmtModified", gmtModified) ? ? ? ? ? ? .append("creatorId", creatorId) ? ? ? ? ? ? .append("modifierId", modifierId) ? ? ? ? ? ? .append("isDeleted", isDeleted) ? ? ? ? ? ? .toString(); ? ? } }
2、創(chuàng)建配置類實(shí)現(xiàn)MetaObjectHandler接口
@Slf4j @Configuration public class MetaObjectHandlerConfig implements MetaObjectHandler { ?? ? ?? ?/** ?? ?*插入時自動填充 ?? ?*/ ? ? @Override ? ? public void insertFill(MetaObject metaObject) { ? ? ? ? //獲得用戶上下文 ? ? ? ? UserContext dscUser = GlobalSessionContext.getDscUser(); ? ? ? ? //獲得當(dāng)前時間 ? ? ? ? Date date = Calendar.getInstance().getTime(); ? ? ? ? //創(chuàng)建時間 ? ? ? ? this.fillStrategy(metaObject, "gmtCreate", date); ? ? ? ? //更新時間 ? ? ? ? this.fillStrategy(metaObject, "gmtModified", date); ? ? ? ? //未刪除 ? ? ? ? this.fillStrategy(metaObject, "isDeleted", CommonConstants.NON_DELETED); ? ? ? ? //創(chuàng)建者 ? ? ? ? this.fillStrategy(metaObject, "creatorId", dscUser.getUserId()); ? ? ? ? //更新者 ? ? ? ? this.fillStrategy(metaObject, "modifierId", dscUser.getUserId()); ? ? } ? ?? ?? ?/** ?? ?*修改時自動填充 ?? ?*/ ? ? @Override ? ? public void updateFill(MetaObject metaObject) { ? ? ? ? //獲得用戶上下文 ? ? ? ? UserContext dscUser = GlobalSessionContext.getDscUser(); ? ? ? ? //獲得當(dāng)前時間 ? ? ? ? Date date = Calendar.getInstance().getTime(); ? ? ? ? //強(qiáng)制更新時間 ? ? ? ? this.setFieldValByName("gmtModified", date, metaObject); ? ? ? ? //更新者 ? ? ? ? this.fillStrategy(metaObject, "modifierId",dscUser.getUserId()); ? ? } }
二、失效場景及解決方案
1、使用mybatis-plus的boolean update(Wrapper updateWrapper)鏈?zhǔn)礁路椒〞r失效
1)示例代碼
/** *更新屬性 */ ?@Override ? ? public Boolean expireHistoryTask(Long tenantId, Long produceInfoId) { ? ? ? ? return this.update(new UpdateWrapper<TaskDetailInfoDO>().lambda() ? ? ? ? ? ? .eq(TaskDetailInfoDO::getTenantId, tenantId) ? ? ? ? ? ? .in(TaskDetailInfoDO::getProduceInfoId, produceInfoId) ? ? ? ? ? ? .eq(TaskDetailInfoDO::getIsDeleted, CommonConstants.NON_DELETED) ? ? ? ? ? ? .set(TaskDetailInfoDO::getTaskStatus, TaskStatusEnum.EXPIRED.getCode()) ? ? ? ? ? ?? ? ? }
2)失效原因
這種更新方法失效我們需要去看mbatis-plus的源碼
private static void process(MappedStatement ms, Object parameterObject) { if (parameterObject != null) { TableInfo tableInfo = null; Object entity = parameterObject; if (parameterObject instanceof Map) { Map<?, ?> map = (Map<?, ?>) parameterObject; if (map.containsKey(Constants.ENTITY)) { Object et = map.get(Constants.ENTITY); if (et != null) { entity = et; tableInfo = TableInfoHelper.getTableInfo(entity.getClass()); } } } else { tableInfo = TableInfoHelper.getTableInfo(parameterObject.getClass()); } //tableInfo為空,則不自動填充 if (tableInfo != null) { //到這里就應(yīng)該轉(zhuǎn)換到實(shí)體參數(shù)對象了,因?yàn)樘畛浜虸D處理都是爭對實(shí)體對象處理的,不用傳遞原參數(shù)對象下去. MetaObject metaObject = ms.getConfiguration().newMetaObject(entity); if (SqlCommandType.INSERT == ms.getSqlCommandType()) { populateKeys(tableInfo, metaObject, entity); insertFill(metaObject, tableInfo); } else { updateFill(metaObject, tableInfo); } } } }
從上面的代碼可以看出,當(dāng)tableInfo為空,則不自動填充字段值。而繼續(xù)看,tableInfo是從parameterObject中獲取,而這parameterObject就是要更新的實(shí)體對象。
在看我們使用 update(Wrapper updateWrapper)更新的底層邏輯
/** * 根據(jù) UpdateWrapper 條件,更新記錄 需要設(shè)置sqlset * * @param updateWrapper 實(shí)體對象封裝操作類 {@link com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper} */ default boolean update(Wrapper<T> updateWrapper) { //傳入了一個空實(shí)體 return update(null, updateWrapper); }
此時是傳了一個空對象,這就導(dǎo)致了整個后續(xù)的填充都失效了。
3)解決方法
使用update的另一個方法
在更新是傳入實(shí)體對象
@Override public Boolean expireHistoryTask(Long tenantId, Long produceInfoId) { return this.update(new TaskDetailInfoDO(), new UpdateWrapper<TaskDetailInfoDO>().lambda() .eq(TaskDetailInfoDO::getTenantId, tenantId) .in(TaskDetailInfoDO::getProduceInfoId, produceInfoId) .eq(TaskDetailInfoDO::getIsDeleted, CommonConstants.NON_DELETED) .set(TaskDetailInfoDO::getTaskStatus, TaskStatusEnum.EXPIRED.getCode()) ); }
2、填充時使用 MetaObjectHandler fillStrategy(MetaObject metaObject, String fieldName, Object fieldVal) 方法
@Override public void updateFill(MetaObject metaObject) { //獲得用戶上下文 UserContext dscUser = GlobalSessionContext.getDscUser(); //更新者 this.fillStrategy(metaObject, "modifierId", dscUser.getUserId()); }
fillStartegy的源碼時這樣的
/** * 填充策略,默認(rèn)有值不覆蓋,如果提供的值為null也不填充 * * @param metaObject metaObject meta object parameter * @param fieldName java bean property name * @param fieldVal java bean property value of Supplier * @since 3.3.0 */ default MetaObjectHandler fillStrategy(MetaObject metaObject, String fieldName, Object fieldVal) { if (getFieldValByName(fieldName, metaObject) == null) { setFieldValByName(fieldName, fieldVal, metaObject); } return this; }
當(dāng)需要更新的字段已經(jīng)有值時,則默認(rèn)不更新。需要強(qiáng)制更新字段時,使用 MetaObjectHandler setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject) 方法更新字段值。
@Override public void updateFill(MetaObject metaObject) { //獲得用戶上下文 UserContext dscUser = GlobalSessionContext.getDscUser(); //獲得當(dāng)前時間 Date date = Calendar.getInstance().getTime(); //更新時間 this.setFieldValByName("gmtModified", date, metaObject); //更新者 this.setFieldValByName("modifierId", metaObject, dscUser.getUserId()); }
到此這篇關(guān)于解決mybatisplus MetaObjectHandler 失效的問題的文章就介紹到這了,更多相關(guān)mybatisplus MetaObjectHandler 失效內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringMVC源碼解讀之HandlerMapping - AbstractUrlHandlerMapping系列re
這篇文章主要介紹了SpringMVC源碼解讀之HandlerMapping - AbstractUrlHandlerMapping系列request分發(fā) 的相關(guān)資料,需要的朋友可以參考下2016-02-02Java使用Collections.sort對中文進(jìn)行排序方式
這篇文章主要介紹了Java使用Collections.sort對中文進(jìn)行排序方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11詳解Spring Boot下使用logback 記錄多個文件日志
這篇文章主要介紹了詳解Spring Boot下使用logback 記錄多個文件日志,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-08-08Springboot通過谷歌Kaptcha?組件生成圖形驗(yàn)證碼功能
Kaptcha是谷歌開源的一款簡單實(shí)用的圖形驗(yàn)證碼組件。我個人推薦它的最大原因是容易上手,采用約定大于配置的方式,快速契合到項(xiàng)目中,這篇文章主要介紹了Springboot通過谷歌Kaptcha組件生成圖形驗(yàn)證碼的方法,需要的朋友可以參考下2023-05-05SpringBoot整合spring-retry實(shí)現(xiàn)接口請求重試機(jī)制及注意事項(xiàng)
今天通過本文給大家介紹我們應(yīng)該如何使用SpringBoot來整合spring-retry組件實(shí)現(xiàn)重試機(jī)制及注意事項(xiàng),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧2021-08-08