实现 公共字段自动填充【创建时间/创建人/修改id/修改id】

cnblogs 2024-08-23 15:39:05 阅读 89

实现 公共字段自动填充【创建时间/创建人/修改id/修改id】

技术栈

    <li>枚举
  1. 自定义注解
  2. AOP
  3. 反射

实现思路

  1. 编写枚举,用于标识数据库操作类型
  2. 自定义注解AutoFill,用于标识需要进行公共字段自动填充的方法
  3. 将Mapper的方法名写成常量类,提高代码规范
  4. 自定义切面类AutoFillAspect,统一拦截加入了AutoFill注解的方法,通过反射为公共字段赋值
  5. 在Mapper的方法上加入AutoFill注解

代码实现

  1. 编写枚举,用于标识数据库操作类型

    <code>public enum OperationType {

    //更新操作

    UPDATE,

    //插入操作

    INSERT

    }

  2. 自定义注解AutoFill,用于标识需要进行公共字段自动填充的方法

    @Target(ElementType.METHOD)

    @Retention(RetentionPolicy.RUNTIME)

    public @interface AutoFill {

    //数据库操作类型

    OperationType value();

    }

  3. 将Mapper的方法名写成常量类,提高代码规范

    //公共字段自动填充相关常量

    public class AutoFillConstant {

    //实体类中的方法名称

    public static final String SET_CREATE_TIME = "setCreateTime";

    public static final String SET_UPDATE_TIME = "setUpdateTime";

    public static final String SET_CREATE_USER = "setCreateUser";

    public static final String SET_UPDATE_USER = "setUpdateUser";

    }

  4. 自定义切面类AutoFillAspect

    /**

    * 自定义切面,实现公共字段自动填充

    */

    @Aspect

    @Component

    @Slf4j

    public class AutoFillAspect {

    /**

    * 切入点

    */

    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")

    public void autoFillPointCut(){}

    /**

    * 前置通知,在通知中进行公共字段的赋值

    */

    @Before("autoFillPointCut()")

    public void autoFill(JoinPoint joinPoint){

    log.info("开始进行公共字段自动填充...");

    //获取到当前被拦截的方法上的数据库操作类型

    MethodSignature signature = (MethodSignature) joinPoint.getSignature();//方法签名对象

    AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);//获得方法上的注解对象

    OperationType operationType = autoFill.value();//获得数据库操作类型

    //获取到被拦截的方法形参参数【实体对象】

    Object[] args = joinPoint.getArgs();

    //约定:如果需要实现自动填充功能 ,需要把实体参数 放在形参第一个参数

    if (args == null || args.length == 0){

    return;//防止空指针

    }

    Object entity = args[0];//拿到实体对象

    //准备数据 实体对象的公共属性【时间和登录id】

    LocalDateTime now = LocalDateTime.now();

    Long currentId = BaseContext.getCurrentId();

    //根据当前不同的操作类型 为对应的属性赋值【反射】

    if (operationType == OperationType.INSERT){

    //为4个公共字段赋值

    try {

    Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);//这里就是常量类,规范代码

    Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);

    Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);

    Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);

    //通过反射为对象属性赋值

    setCreateTime.invoke(entity,now);

    setCreateUser.invoke(entity,currentId);

    setUpdateTime.invoke(entity,now);

    setUpdateUser.invoke(entity,currentId);

    } catch (Exception e) {

    e.printStackTrace();

    }

    }else if (operationType == OperationType.UPDATE){

    //为2个公共字段赋值

    try {

    Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);

    Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);

    //通过反射为对象属性赋值

    setUpdateTime.invoke(entity,now);

    setUpdateUser.invoke(entity,currentId);

    } catch (Exception e) {

    e.printStackTrace();

    }

    }

    }

    }

  5. 在Mapper的方法上加入AutoFill注解

    @AutoFill(value = 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);

实现了表格公共字段自动填充后,在service层编写插入或者修改实体的时候就不需要重复设置 修改时间、修改id等

//设置修改时间、修改人

// category.setUpdateTime(LocalDateTime.now());

// category.setUpdateUser(BaseContext.getCurrentId());这些不再需要重复设置



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。