公共字段自动填充——后端

场景:当处理一些请求时,会重复的对数据库的某些字段进行赋值(如:在插入和更新某个物品时,需要更新该物品的更新时间和更新者的信息),这样会导致代码冗余。
如:
在这里插入图片描述
思路:

  • 自定义注解 AutoFill,用于标识需要进行公共字段自动填充的方法
  • 自定义切面类 AutoFillAspect,统一拦截加入了 AutoFill 注解的方法,通过反射为公共字段赋值
  • 在 Mapper 的方法上加入 AutoFill 注解

实现:
定义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;

/**
 * ClassName: AufoFill
 * PackageName: com.sky.Annotation
 * Description: 用于表示某个方法需要进行功能字段自动填充处理
 *
 * @Author Xiyan Zhong
 * @Create 2023/12/18 下午2:55
 * @Version 1.0
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {
    // 数据库操作类型:UPDATE INSERT
    OperationType value();
}

实现切面类:

package com.sky.aspect;

import com.sky.annotation.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
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.lang.reflect.Method;
import java.time.LocalDateTime;

/**
 * ClassName: AutoFillAspect
 * PackageName: com.sky.Aspect
 * Description:自定义切面,实现公共字段自动填充逻辑
 *
 * @Author Xiyan Zhong
 * @Create 2023/12/18 下午3:00
 * @Version 1.0
 */

@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 annotation = signature.getMethod().getAnnotation(AutoFill.class);// 获取方法上的注解对象
        OperationType operationType = annotation.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_CREATE_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) {
            try {
                // 为2个公共字段赋值
                Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME ,LocalDateTime.class);
                Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);

                // 通过反射为对象属性赋值
                setUpdateTime.invoke(entity,now);
                setUpdateUser.invoke(entity,currentId);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

需要注意的是,在反射中获取方法名时和判断拦截方法的类型时,分别采用的是常量枚举,而不是直接使用方法的字符串名称,这样可以降低编码时的错误率,也更加规范,对应的代码:

package com.sky.constant;

/**
 * 公共字段自动填充相关常量
 */
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";
}

/**
 * 数据库操作类型
 */
package com.sky.enumeration;

/**
 * 数据库操作类型
 */
public enum OperationType {

    /**
     * 更新操作
     */
    UPDATE,

    /**
     * 插入操作
     */
    INSERT

}

在Mapper对应的方法中,添加注解@AutoFill:

    /**
     * 插入数据
     * @param category
     */
    @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})")
    @AutoFill(OperationType.INSERT)
    void insert(Category category);

    /**
     * 根据id修改分类
     * @param category
     */
    @AutoFill(OperationType.UPDATE)
    void update(Category category);

删除对应的服务实现类的赋值操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/254649.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

避免付费搜索广告系列与有机搜索广告系列之间出现关键词蚕食现象

自然搜索(搜索引擎优化)和付费搜索(或按点击付费)具有足够的技术复杂性和战略方面。 关键词蚕食是一个可能使它们变得更加困难的问题——如果你的搜索引擎优化 (SEO) 和按点击付费 (PPC&#x…

【Python】获取B站粉丝列表保存至数据库中

分析网络请求,获取到有粉丝接口的数据url 可以在响应信息处看到粉丝的信息 通过浏览器也可以直接请求到具体的JSON信息 通过独立的标签我们可以看到接口数据,但是要注意如果不是查看自己登录账户的接口那么就无法查询到所有粉丝的数据,默认只…

Python通过函数名调用函数的几种场景

前言 大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 如果有什么疑惑/资料需要的可以点击文章末尾名片领取源码 除了执行系统命令外,我们有时还需要动态地执行一些python代码,有经验的朋友就会知道可以使用内置函数eval实现这一需求,如eval(“…

Appcelerator打包ipa有哪些优势

大家好,我是咕噜-凯撒,我们得先知道Appcelerator是啥,Appcelerator(现在更名为Axway Titanium)是一个跨平台的移动应用开发框架通过提供一种简化和加速移动应用开发的方式帮助你构建高质量的跨平台应用程序。那使用App…

【基础篇】YOLO系列训练环境(GPU)搭配篇

🚀Pytorch环境配置(Windows) 🔨 Anaconda安装 此处下载安装即可 ⭐温馨提示:安装路径不能含有中文,建议不要安在c盘(很占内存) 环境变量配置 编辑系统环境变量 -> 环境变量 -> 系统变量 新建并添加以下路径 打开cmd,输入conda&

设计模式—装饰模式

与其明天开始,不如现在行动! 文章目录 装饰模式—穿衣服💎总结 装饰模式—穿衣服 装饰模式(Decorator)可以动态的给对象添加一些额外的职责。 Component是定义一个对象接口,可以给这些对象动态地添加职责。…

【深度学习目标检测】十、基于yolov5的火灾烟雾识别(python,目标检测)

YOLOv5是目标检测领域一种非常优秀的模型,其具有以下几个优势: 1. 高精度:YOLOv5相比于其前身YOLOv4,在目标检测精度上有了显著的提升。YOLOv5使用了一系列的改进,如更深的网络结构、更多的特征层和更高分辨率的输入图…

Vditor - Markdown编辑器使用

1、安装 yarn add vditor2、代码 import vditor/dist/index.css; import React, { useEffect } from react; import Vditor from vditor; import ./index.less;const App ({ setVditorValue, vditorValue }: any) > {const [vd, setVd] React.useState<Vditor>();…

Redis-网络模型

参考资料 &#xff1a;极客时间 Redis&#xff08;亚风&#xff09; 前置知识 系统隔离 为了避免⽤户应⽤导致冲突甚⾄内核崩溃&#xff0c;⽤户应⽤与内核是分离的&#xff1a; 进程的寻址空间会划分为两部分&#xff1a;内核空间、⽤户空间 • ⽤户空间只能执⾏受限的命令&…

激活函数-SwiGLU

SwiGLU SiLU 函数是一种神经网络中的激活函数&#xff0c;全称是 Sigmoid Linear Unit, 也被称为 Swish 函数。它由 Google Brain 在 2017 年提出&#xff0c;是一种非线性激活函数&#xff0c;能够有效地对神经网络的输入进行非线性变换。 定义 f ( x ) x ∗ σ ( x ) f(x)…

vue3使用vue-router嵌套路由(多级路由)

文章目录 1、Vue3 嵌套路由2、项目结构3、编写相关页面代码3.1、编写route文件下 index.ts文件3.2、main.ts文件代码&#xff1a;3.3、App.vue文件代码&#xff1a;3.4、views文件夹下的Home文件夹下的index.vue文件代码&#xff1a;3.5、views文件夹下的Home文件夹下的Tigerhh…

生命在于学习——TV电视盒子渗透测试抓包设置

一、前言 封面图是示例图&#xff0c;因为涉及到保密&#xff0c;所以本次测试的电视盒子不放出外观和设置界面。 这一次要测试电视盒子&#xff0c;大家也都知道&#xff0c;市面上的电视盒子大部分都是Android&#xff0c;当然&#xff0c;要使用笔记本去抓电视盒子的数据包…

圣诞节来了,为大家送上专属圣诞树

Hello大家好&#xff0c;我是Dream。 今天给大家分享一下我很早之前做过的圣诞树&#xff0c;分享给大家&#xff0c;希望可以帮助到大家度过一个浪漫的圣诞节~ Python打造专属于你的圣诞树落叶雪花背景音乐浪漫弹窗 五合一版圣诞树 一、背景故事圣诞节风波❤️❤️❤️ 二、五…

针对海量数据的存储与访问瓶颈的解决方案

背景 在当今这个时代&#xff0c;人们对互联网的依赖程度非常高&#xff0c;也因此产生了大量的数据&#xff0c;企业视这些数据为瑰宝。而这些被视为瑰宝的数据为我们的系统带来了很大的烦恼。这些海量数据的存储与访问成为了系统设计与使用的瓶颈&#xff0c;而这些数据往往存…

内网BUG管理系统本地部署并结合内网穿透实现异地远程访问

文章目录 前言1. 本地安装配置BUG管理系统2. 内网穿透2.1 安装cpolar内网穿透2.2 创建隧道映射本地服务3. 测试公网远程访问4. 配置固定二级子域名4.1 保留一个二级子域名5.1 配置二级子域名6. 使用固定二级子域名远程 前言 BUG管理软件,作为软件测试工程师的必备工具之一。在…

Windows如何安装使用TortoiseSVN客户端并实现公网访问本地SVN Server

文章目录 前言1. TortoiseSVN 客户端下载安装2. 创建检出文件夹3. 创建与提交文件4. 公网访问测试 前言 TortoiseSVN是一个开源的版本控制系统&#xff0c;它与Apache Subversion&#xff08;SVN&#xff09;集成在一起&#xff0c;提供了一个用户友好的界面&#xff0c;方便用…

泛型深入理解

泛型的概述 泛型&#xff1a;是JDK5中引入的特性&#xff0c;可以在编译阶段约束操作的数据类型&#xff0c;并进行检查。 泛型的格式&#xff1a;<数据类型>; 注意&#xff1a;泛型只能支持引用数据类型。 集合体系的全部接口和实现类都是支持泛型的使用的。 泛型的…

周周清(3)

周一&#xff1a; 写了一道算法题&#xff0c;然后由于身体原因&#xff0c;在宿舍休息了很久&#xff1b;然后还是完成了一道算法题&#xff1a;写了一道LRC缓存题&#xff0c;之前就开始写了&#xff0c;写了很久&#xff0c;每次都开始动笔&#xff0c;刚开始用的是队列加m…

太阳能电池效能IV测试PV检测太阳光模拟器

目录 概述 一、系统组成 产品特点&#xff1a; 技术参数 数字源表 本系统支持Keithley24xx系列源表 标准太阳能电池 低阻测试夹具 自动化测试软件 概述 太阳能光伏器件的所有性能表征手段中&#xff0c;IV特性测试无疑是最直观、最有效、最被广泛应用的一种…

智能配电房运维

智能配电房运维是指利用先进的信息化技术&#xff0c;依托电力智慧运维工具-电易云&#xff0c;对配电房的电气运行设备进行实时在线监测、集中监控和故障诊断处理&#xff0c;以提高设备维护效率、降低停电损失、提高用电效益&#xff0c;并消除用户终端配电系统的安全隐患。 …