解決mybatisplus MetaObjectHandler 失效的問題
一、什么是metaObjectHandler
MetaObjectHandler接口是mybatisPlus為我們提供的的一個擴展接口,我們可以利用這個接口在我們插入或者更新數(shù)據(jù)的時候,為一些字段指定默認值
使用方式如下:
1、在實體類上加入@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)建配置類實現(xiàn)MetaObjectHandler接口
@Slf4j
@Configuration
public class MetaObjectHandlerConfig implements MetaObjectHandler {
?? ?
?? ?/**
?? ?*插入時自動填充
?? ?*/
? ? @Override
? ? public void insertFill(MetaObject metaObject) {
? ? ? ? //獲得用戶上下文
? ? ? ? UserContext dscUser = GlobalSessionContext.getDscUser();
? ? ? ? //獲得當前時間
? ? ? ? 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();
? ? ? ? //獲得當前時間
? ? ? ? Date date = Calendar.getInstance().getTime();
? ? ? ? //強制更新時間
? ? ? ? this.setFieldValByName("gmtModified", date, metaObject);
? ? ? ? //更新者
? ? ? ? this.fillStrategy(metaObject, "modifierId",dscUser.getUserId());
? ? }
}二、失效場景及解決方案
1、使用mybatis-plus的boolean update(Wrapper updateWrapper)鏈式更新方法時失效
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) {
//到這里就應該轉(zhuǎn)換到實體參數(shù)對象了,因為填充和ID處理都是爭對實體對象處理的,不用傳遞原參數(shù)對象下去.
MetaObject metaObject = ms.getConfiguration().newMetaObject(entity);
if (SqlCommandType.INSERT == ms.getSqlCommandType()) {
populateKeys(tableInfo, metaObject, entity);
insertFill(metaObject, tableInfo);
} else {
updateFill(metaObject, tableInfo);
}
}
}
}從上面的代碼可以看出,當tableInfo為空,則不自動填充字段值。而繼續(xù)看,tableInfo是從parameterObject中獲取,而這parameterObject就是要更新的實體對象。
在看我們使用 update(Wrapper updateWrapper)更新的底層邏輯
/**
* 根據(jù) UpdateWrapper 條件,更新記錄 需要設置sqlset
*
* @param updateWrapper 實體對象封裝操作類 {@link com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper}
*/
default boolean update(Wrapper<T> updateWrapper) {
//傳入了一個空實體
return update(null, updateWrapper);
}此時是傳了一個空對象,這就導致了整個后續(xù)的填充都失效了。
3)解決方法
使用update的另一個方法

在更新是傳入實體對象
@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的源碼時這樣的
/**
* 填充策略,默認有值不覆蓋,如果提供的值為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;
}當需要更新的字段已經(jīng)有值時,則默認不更新。需要強制更新字段時,使用 MetaObjectHandler setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject) 方法更新字段值。
@Override
public void updateFill(MetaObject metaObject) {
//獲得用戶上下文
UserContext dscUser = GlobalSessionContext.getDscUser();
//獲得當前時間
Date date = Calendar.getInstance().getTime();
//更新時間
this.setFieldValByName("gmtModified", date, metaObject);
//更新者
this.setFieldValByName("modifierId", metaObject, dscUser.getUserId());
}
到此這篇關于解決mybatisplus MetaObjectHandler 失效的問題的文章就介紹到這了,更多相關mybatisplus MetaObjectHandler 失效內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringMVC源碼解讀之HandlerMapping - AbstractUrlHandlerMapping系列re
這篇文章主要介紹了SpringMVC源碼解讀之HandlerMapping - AbstractUrlHandlerMapping系列request分發(fā) 的相關資料,需要的朋友可以參考下2016-02-02
Java使用Collections.sort對中文進行排序方式
這篇文章主要介紹了Java使用Collections.sort對中文進行排序方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11
詳解Spring Boot下使用logback 記錄多個文件日志
這篇文章主要介紹了詳解Spring Boot下使用logback 記錄多個文件日志,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-08-08
Springboot通過谷歌Kaptcha?組件生成圖形驗證碼功能
Kaptcha是谷歌開源的一款簡單實用的圖形驗證碼組件。我個人推薦它的最大原因是容易上手,采用約定大于配置的方式,快速契合到項目中,這篇文章主要介紹了Springboot通過谷歌Kaptcha組件生成圖形驗證碼的方法,需要的朋友可以參考下2023-05-05
SpringBoot整合spring-retry實現(xiàn)接口請求重試機制及注意事項
今天通過本文給大家介紹我們應該如何使用SpringBoot來整合spring-retry組件實現(xiàn)重試機制及注意事項,本文通過實例代碼給大家介紹的非常詳細,需要的朋友參考下吧2021-08-08

