1.先說場景,在對mysql數據庫表數據插入或者更新時都得記錄時間和用戶id
傳統實現有點繁瑣,這里還可以封裝一下公共方法。
2.解決方法:
? ? 2.1:使用aop切面編程(記錄一下,有時間再攻克)。
? ? ? ? 2.1.1:成功實現進行補充,感謝網友頂力相助(進步·于辰)
? ? ? ? ?2.1.2:在啟動器上加? ?@EnableAspectJAutoProxy
? ? ? ? ?2.1.3:切入主要代碼
@Aspect
@Component
@Slf4j
public class EntityAttrAspect {@Before("execution(* com.zuodou..*.save*(..))"+" ||execution(* com.zuodou..*.update*(..))")public void before(JoinPoint joinPoint) throws Exception {log.info("切入");String userId = BaseUtlis.getCurrentUser().getId();// 管理員idObject[] args = joinPoint.getArgs();for (Object arg : args) {if (arg != null) {Class<?> clazz = arg.getClass();// 獲取實體所有屬性,進而獲取主鍵屬性。一般情況下,主鍵屬性是第一個Class<?> entityClass = clazz; // 使用clazz獲取實體類的類型Field[] entityFieldArr = entityClass.getDeclaredFields();Field idField = entityFieldArr[0];// 主鍵屬性idField.setAccessible(true);//設置為可以訪問Object id = idField.get(arg); // 使用arg獲取實體對象的主鍵值if (id == null) {// 無主鍵,插入if (StringUtils.isNotBlank(userId)){entityAttrIoc(arg, "createBy", userId);// 創建人}entityAttrIoc(arg, "createTime", new Date());// 創建時間} else {// 有主鍵,更新if (StringUtils.isNotBlank(userId)){entityAttrIoc(arg, "updateBy", userId);// 修改人}entityAttrIoc(arg, "updateTime", new Date());// 更新時間}}}}// entityAttrIoc方法的定義可以是類似于下面這樣的形式:private void entityAttrIoc(Object entity, String attributeName, Object value) throws Exception {Field field = entity.getClass().getDeclaredField(attributeName);field.setAccessible(true);field.set(entity, value);}}
? ? 注:
@Before("execution(* com.zuodou..*.save*(..))"+ " ||execution(* com.zuodou..*.update*(..))" )切入點的表達式,不懂了可以先去了解表達式配置
我只需要判斷新增還是修改,
Field idField = entityFieldArr[0];// 主鍵屬性 idField.setAccessible(true);//設置為可以訪問我主鍵是由? file? 和? static? 修飾的? 所以得加setAccessible
? ? 2.2:使用@TableField()注解。
3.我使用的@TableField? 注解實現,因為沒有很多的業務處理,單純的記錄一下,以下是具體實現
@Component public class MyMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {// 在插入時自動填充 create_time 和 update_time 字段this.strictInsertFill(metaObject, "createTime", Date.class, new Date());this.strictInsertFill(metaObject, "createBy", String.class, BaseUtlis.getCurrentUser().getId());}@Overridepublic void updateFill(MetaObject metaObject) {// 在更新時自動填充 update_time 字段this.strictUpdateFill(metaObject, "updateTime",Date.class, new Date());this.strictInsertFill(metaObject, "updateBy", String.class, BaseUtlis.getCurrentUser().getId());} }
注: 字段需要跟實體類對應起來,我項目架構是使用了駝峰命名使用下劃線后字母大寫。BaseUtlis.getCurrentUser().getId(),這個是我封裝的一個獲取當前登錄用戶的方法。
參數解析:
this.strictUpdateFill(metaObject, "updateTime",Date.class, new Date());
metaObject:對象
updateTime:實體類目標字段
Date.class:數據類型
new Date():具體值
4.yml配置
mybatis-plus:global-config:db-config:meta-object-handler: com.zuodou.mymeta.MyMetaObjectHandler
5.在對應實體類的字段上加
@TableField(fill = FieldFill.UPDATE)
或者
@TableField(fill = FieldFill.INSERT)
6.補充缺陷
直接在controllerdi調用根據id修改方法? ?或者 update 批量根據id修改,?會不觸發自動填充
解決使用update,條件傳入id或者在service調用,而updateBatchById就需要手動傳了。
至于為什么在service調用updateById就能觸發
在 MyBatis Plus 中,通常通過繼承 ServiceImpl 類來實現 Service 層的操作。這個類提供了一些默認的 CRUD(增刪改查)方法,并且默認情況下會使用 MyBatis Plus 的內置功能,比如自動填充。
當你在自己的 Service 類中繼承了 ServiceImpl 并且指定了泛型類型,比如 YourService extends ServiceImpl<YourMapper, YourEntity>,這樣就將 YourService 和 YourEntity 關聯起來了。
MyBatis Plus 的 ServiceImpl 已經預先實現了一些常見的操作方法,其中包括了自動填充的支持。在這個類中,如果你調用了 updateById 方法,它內部會調用 MyBatis Plus 的自動填充邏輯,以便在更新數據時觸發自動填充。
當然,前提是你需要做以下幾件事情:1.確保你的實體類中的字段有正確地標注了自動填充的注解,比如使用了 @TableField 注解并設置了相應的 fill 屬性。
2.確保你已經正確配置了 MetaObjectHandler,并且這個配置被正確地注冊到了 Spring 容器中。這樣 MyBatis Plus 才能正確地使用自動填充功能。因此,當你在自定義的 Service 類中繼承了 ServiceImpl,就相當于在你的 Service 類中內置了 MyBatis Plus 提供的默認實現,包括自動填充的支持。這樣,在調用 updateById 等方法時,會自動觸發 MyBatis Plus 的自動填充邏輯。
(侵權聯系刪除)