问题分析
实现思路
- 对mapper定义
注解
,使用切面
思想来判断是不是更新和新增操作 - 对于指定的操作来更新公共字段
自定义操作类型
package com.sky.enumeration;
public enum OperationType {
UPDATE,
INSERT
}
自定义注解AutoFill
package com.sky.annotation;
import com.sky.enumeration.OperationType;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {
OperationType value();
}
自定义切面
- 定义切点
- 获取当前的mapper方法的具体操作类型
- 获取当前的mapper方法的参数 实体对象entity
- 获取要填充的数据
- 根据操作类型进行填充
package com.sky.aspect;
import cn.hutool.core.util.ObjectUtil;
import com.sky.annotation.AutoFill;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import com.sky.exception.BaseException;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import static com.sky.constant.AutoFillConstant.*;
import static com.sky.constant.MessageConstant.AUTO_FILL_FAILED;
@Aspect
@Component
@Slf4j
public class AutoFillAspect {
@Pointcut("execution(* com.sky.mapper..*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
public void autoFillPointCut() {}
@Before("autoFillPointCut()")
public void before(JoinPoint joinPoint) {
log.info("自动填充切面执行");
MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
OperationType operationType = methodSignature.getMethod().getAnnotation(AutoFill.class).value();
Object[] args = joinPoint.getArgs();
if(ObjectUtil.isEmpty(args)) return;
Object entity = args[0];
Long currentUserId = BaseContext.getCurrentId();
LocalDateTime now = LocalDateTime.now();
switch (operationType) {
case INSERT:
try {
entity.getClass().getMethod(SET_CREATE_USER, Long.class).invoke(entity, currentUserId);
entity.getClass().getMethod(SET_UPDATE_USER, Long.class).invoke(entity, currentUserId);
entity.getClass().getMethod(SET_CREATE_TIME, LocalDateTime.class).invoke(entity, now);
entity.getClass().getMethod(SET_UPDATE_TIME, LocalDateTime.class).invoke(entity, now);
} catch (Exception e) {
log.error(AUTO_FILL_FAILED, e);
throw new BaseException(AUTO_FILL_FAILED);
}
break;
case UPDATE:
try {
entity.getClass().getMethod(SET_UPDATE_USER, Long.class).invoke(entity, currentUserId);
entity.getClass().getMethod(SET_UPDATE_TIME, LocalDateTime.class).invoke(entity, now);
} catch (Exception e) {
log.error(AUTO_FILL_FAILED, e);
throw new BaseException(AUTO_FILL_FAILED);
}
break;
default:
break;
}
}
}
使用
@AutoFill(OperationType.UPDATE)
void update(Category category);
@AutoFill(OperationType.INSERT)
@Insert("insert into category(type, name, sort, status, create_time, update_time, create_user, update_user)" +
" VALUES" +
" (#{type}, #{name}, #{sort}, #{status}, #{createTime}, #{updateTime}, #{createUser}, #{updateUser})")
void insert(Category category);