公共字段自动填充功能实现【springboot】

问题分析

很多业务表里面有相同的公共字段,导致每次插入都要写相同的代码,代码冗余,不便于后期维护

公共字段填充是解决​​重复性字段统一管理​​问题的技术方案,主要用于自动处理实体类中那些在多处重复出现且赋值逻辑相同的字段(如创建时间、创建人、更新时间等)。

解决思路

代码实现

1,自定义注解

指定添加注解的地方

2,自定义切面类。切面=切入点+通知

定义切入点,确定切入点位置

定义通知,确定通知类型,通知要执行的操作

3,先给需要自动装配的方法加上注解,测试一下,再写通知操作

通知要执行的操作

1,获取方法对数据库操作类型,确定要填充的字段

  • 利用方法签名对象和反射获取注解对象

2,获取当前拦截的方法的参数(实体对象)

  • 判断防止出现空指针,接收对象用object最好

3,准备要赋值的数据

  • 利用ThreadLocal和其他工具类

4,根据不同的数据库操作类型,利用反射进行赋值

  • 利用反射获取需要装配的字段的set方法。
  • 利用invoke方法进行赋值。invoke()反射核心方法,第一个参数是调用对象实例,后续是方法参数。
java 复制代码
//指定注解只能加在方法上
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {
    //数据库操作类型;update insert
    //指定当前数据库操作类型是更新还是插入,只有在插入或者更新的时候才需要自动填充功能
    OperationType value();
}
java 复制代码
@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];
        //准备赋值的数据
        LocalDateTime now = LocalDateTime.now();
        Long currentId = BaseContext.getCurrentId();
        //根据不同的操作类型,为对应的属性赋值
        if (operationType == OperationType.INSERT) {
            //为四个公共字段赋值
            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) {
                throw new RuntimeException(e);
            }


        } else if (operationType == OperationType.UPDATE) {
            //为两个公共字段赋值
            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) {
                throw new RuntimeException(e);
            }

        }
    }
}
相关推荐
Full Stack Developme35 分钟前
Java 日期时间处理:分类、用途与性能分析
java·开发语言·数据库
雪碧聊技术3 小时前
存储过程的介绍、基本语法、delimiter的使用
数据库·存储过程的基本语法·delimiter的使用
_码农121384 小时前
spring boot 使用mybatis简单连接数据库+连表查询
数据库·spring boot·mybatis
TTBIGDATA6 小时前
【支持Ubuntu22】Ambari3.0.0+Bigtop3.2.0——Step7—Mariadb初始化
数据库·ambari·hdp·mariadb·bigtop·ttbigdata·hidataplus
大得3697 小时前
django的数据库原生操作sql
数据库·sql·django
tuokuac7 小时前
SQL中的HAVING用法
数据库·sql
爬山算法7 小时前
MySQL(173)MySQL中的存储过程和函数有什么区别?
数据库·mysql
jnrjian7 小时前
利用trigger对大表在线同步 UDI
数据库·sql
Ruimin05197 小时前
Mysql集群技术
数据库·mysql
lifallen7 小时前
深入解析RocksDB的MVCC和LSM Tree level
大数据·数据结构·数据库·c++·lsm-tree·lsm tree