首页 > 其他分享 >002_公共字段公共填充

002_公共字段公共填充

时间:2024-01-26 20:44:40浏览次数:25  
标签:mapper 填充 entity 002 AutoFill 公共 注解 class 赋值

每次进行增加员工或者修改员工之类,有关修改和新增的操作时,要对修改时间、新增时间、修改人、新增人这几个字段进行修改,代码比较重复。

用切面,前置通知,对Mapper中的方法进行捕获。这些都是我们操作的对象中的字段,原本这些字段是在service的实现类中进行赋值。

用注解进行标识,有@AutoFill就表示当前方法要进行捕获,捕获了之后就把那几个字段进行修改。代码只用写一份,只要有注解就会执行这个进行公共属性赋值的代码。

step1 自定义注解AutoFill,用于表示需要进行公共字段自动填充的方法

/**
 * 自定义注解
 * 用于表示某个方法需要进行字段自动填充
 */
@Target(ElementType.METHOD) //表示用于方法的标识
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {

    //数据库操作类型:UPDATE、INSERT  update和insert要赋值的属性数量不一样,定义这个属性可以用于区分
    OperationType value();//注解的属性
}

step2 自定义切面类AutoFillAspect,统一拦截加入了AutoFill注解的方法,通过反射为对象属性赋值

/**
 * 自定义切面
 * 实现公共字段自动填充处理逻辑
 */
@Aspect
@Component //交给spring容器来管理
@Slf4j
public class AutoFillAspect {

    /**
     * 切入点
     */
    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)") //匹配mapper包下的所有类下的所有方法中的 有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();//获得数据库操作类型

        //获取到当前被拦截的方法的参数--实体对象
        //这个对象已经在service的实现类中被操作过了 例如员工新增这个操作,账号姓名性别等等这些是属性已经在serviceImpl中进行赋值了,但是修改时间、新增时间..这些属性是公共属性、是重复的,我们放到mapper中进行赋值。将mapper中的新增员工方法拦截,然后加上注解,就可以执行这里的代码了。
        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 {
                //获取到实体类中的setter操作的方法
                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();
            }
        }
        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) {
                e.printStackTrace();
            }
        }

    }
}

step3 在Mapper的方法上加入AutoFill注解

@AutoFill(OperationType.UPDATE)
void update(Employee employee);

为什么注解加载了mapper中,我的理解是:

serviceImpl中传入的对象是前端传过来的封装好的对象,然后我们会将其封装成实体类,传给mapper,最终在mapper中的方法的参数是我们需要的实体类,最终传入数据库的就是这个实体类。如果采用前置通知,在mapper中的方法执行之前进行最后的封装,这才是完整的实体类。如果要将注解用在serviceImpl中的话,应该采用的是后置通知吧。

标签:mapper,填充,entity,002,AutoFill,公共,注解,class,赋值
From: https://www.cnblogs.com/jyyyy/p/17990656

相关文章

  • SQL002 BCPコマンド
    BCPは「BulkCopyProgram」の略称。BCPコマンドによって以下のようなことができます。・テーブル内のデータをファイルに一括エクスポートする・予め作成したファイルのデータをテーブルに一括インポートするBCPを使う利点・大量データを(楽に)扱える・DBとのインポート/エ......
  • LG10026
    看完题目后,发现直接对\(a\)模拟操作的情况过多,不好处理。但如果对\(n\)进行逆向操作,似乎可以在很少步数内就变为\(1\)。我们大胆猜想,用最少的步数使\(n\)变为\(1\),再考虑如何处理多余的次数(若次数不足则直接无解)。先列出转换后的操作:\(n\getsn+1\);\(n\getsn\div2......
  • Hive报错:Call From hadoop01/172.23.238.2 to hadoop01:10020 failed on connection e
    问题描述在阿里云服务器上安装的Hadoop和Hive,刚开始关闭了防火墙。但是由于服务器被被黑客安装挖矿程序,所以开启了防火墙。但是即使开启了所有可能的端口,但是在向Hive中插入数据时,依然报错提示:CallFromhadoop01/172.23.238.2tohadoop01:10020failedonconnectionexception......
  • VBA002 全角文字・半角文字を相互変換する方法
    StrConv関数の使い方StrConv(文字列,変換方法)変換方法は全角文字・半角文字の相互変換以外にもいくつかあるので、表形式で一覧にしました。No 値 意味1 vbUpperCase 大文字に変換2 vbLowerCase 小文字に変換3 vbProperCase 各単語の先頭の文字を大文字に変換4 vbWi......
  • 代码随想录 day22 二叉搜索树的最近公共祖先 二叉搜索树中的插入操作 删除二叉搜索树
    二叉搜索树的最近公共祖先这题跟之前的不一样可以利用二叉搜索树有序的特点有序就说明可以根据节点的值与pq的关系判断应该往左边搜索还是右边搜索这题显然是不需要遍历整棵树的所以是写的遍历边的写法遍历树需要用变量接受二叉搜索树中的插入操作一开始还以为要遍历......
  • 二叉树的公共祖先
    最开始做的时候,就先想到的是找父节点的那个函数,于是先把目标节点的所以祖先节点存起来,然后一个一个进行比对,当然这样耗时很大。点击查看代码classSolution{public:vector<TreeNode*>vp,vq;TreeNode*findfa(TreeNode*root,TreeNode*k){if(!root){returnNULL;}if(ro......
  • 代码随想录 day21 二叉搜索树的最小绝对差 二叉搜索树中的众数 二叉树的最近公共祖先
    二叉搜索树的最小绝对差二叉搜索树就是有序数组那么转换一下就很简单了也可以直接在遍历二叉搜索树的时候进行比较需要一个指针记录前一个节点二叉搜索树中的众数既可以把这题的二叉搜索树当成一般树来做这样就是层序遍历树然后用map记录频率再取频率最高的值这里用......
  • flask-study-002
    本篇主要记录flask的模板使用1.模板基本使用通过render_template函数进行模板的渲染在app.py同级目录下,创建templates目录,用于存放需要flask渲染的模板fromflaskimportFlask,render_templateapp=Flask(__name__)app.config['DEBUG'][email protected]('/')def......
  • P1002题解
    思路设\(dp_{i,j}\)表示第\(i\)行\(j\)列卒走到这里有多少种方式。卒是可以向右和下走,所以到这个点只能从左或上来,不难得出转移公式:\(dp_{i,j}=dp_{i-1,j}+dp_{i,j-1}\)。如果马在这个点上或者说马能到这个点上,那么卒不能到这个点,也就是卒到这个点的方式为\(0\)。如......
  • flask学习002
    本篇学习实践flask的模板渲染导入render_template模板在app.py同级目录下,创建templates目录,创建user.html<h1>hello,{{name}}我是模板内容</h1>目录结构:.├──app.py└──templates└──user.htmlapp.py代码修改如下:fromflaskimportFlask,render......