MyBatis自動設定建立時間和更新時間

Coder马里奥發表於2024-06-04

需求

     使用 MyBatis 插入或修改某條記錄時,能自動設定資料表裡的 create_time 和 update_time 欄位,即自動給實體類物件的 createTime 和 updateTime 屬性賦值。(如果使用 MyBatis-Plus,該功能很容易實現,現在針對的場景是僅使用 MyBatis)

解決方案

​    使用AOP的思想,在執行新增或修改前,用反射獲取方法的第一個引數,給它的 createTime 和 updateTime 屬性賦值 。(約定:方法的第一個引數是要操作的實體類)

程式碼

1、自定義註解:

/**
 * 標識 需要自動填充的方法
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {
    OperationType value();
}

2、列舉類:指定方法型別是 insert 還是 update,insert 操作需要 同時設定 createTime 和 updateTime,update操作只設定 updateTime 。

/**
 * 操作型別
 */
public enum OperationType {
    UPDATE,
    INSERT
}

3、切面:

/**
 * 自定義切面 自動填充公共欄位
 */
@Aspect
@Component
public class AutoFillAspect {

    /**
     * 切入點
     *   * com.example.mapper.*.*(..)  需要能定位到mapper介面的位置
     *   com.example.autofill.AutoFill  是上面寫的自定義註解的路徑
     */
    @Pointcut("execution(* com.example.mapper.*.*(..)) && @annotation(com.example.autofill.AutoFill)")
    public void autoFillPointCut() {
    }


    /**
     * 前置通知,insert update之前 填充時間
     */
    @Before("autoFillPointCut()")
    public void autoFill(JoinPoint joinPoint) throws Exception {
        //獲取到當前被攔截的方法上的資料庫操作型別
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();//方法簽名物件
        AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);//獲得方法上的註解物件
        OperationType operationType = autoFill.value();//獲得資料庫操作型別   insert  update
        // insert  update  方法引數是實體類 需要放在第一個
        // 獲取實體引數物件
        Object[] args = joinPoint.getArgs();
        if (args == null || args.length == 0) {
            return;
        }
        Object entity = args[0];
        // 為 createTime 和 updateTime 屬性賦值
        LocalDateTime localDateTime = LocalDateTime.now();
        if (operationType == OperationType.INSERT) {
            // insert 操作 兩個時間都賦值
            Method setCreateTime = entity.getClass().getMethod(SET_CREATE_TIME, LocalDateTime.class);
            Method setUpdateTime = entity.getClass().getMethod(SET_UPDATE_TIME, LocalDateTime.class);
            setCreateTime.invoke(entity, localDateTime);
            setUpdateTime.invoke(entity, localDateTime);
        } else if (operationType == OperationType.UPDATE) {
            // update 操作 只設定更新時間
            Method setUpdateTime = entity.getClass().getMethod(SET_UPDATE_TIME, LocalDateTime.class);
            setUpdateTime.invoke(entity, localDateTime);
        }
    }
}

測試案例

實體類:

import lombok.Data;
import java.time.LocalDateTime;

@Data
public class User{
    private Long id;
    private String name;
    private LocalDateTime createTime;
    private LocalDateTime updateTime;
}

mapper介面:

/**
 * 新增使用者
 */
@AutoFill(value = OperationType.INSERT)
Integer addUser(User user);

xml檔案:

<insert id="addUser" parameterType="user" useGeneratedKeys="true" keyProperty="id">
    insert into user(name, create_time, update_time)
    values (#{name}, #{createTime}, #{updateTime})
</insert>

測試方法:

@Resource
private UserMapper userMapper;

void test(){
    User user = new User();
    user.setName("張三");  // 無需手動設定 createTime 和 updateTime 屬性
    userMapper.addUser(user);
}

相關文章