日常开发,每张表中的operator、gmt_create、gmt_modified,你是怎么处理的?

9 篇文章 0 订阅

日常开发的数据库设计环节,相信大家都会有这样一种感受,每张表都会有这些基本信息, creator_id, creator, created_at, updater_id, updater, updated_at , 我暂且称为元数据(MetaInfo)吧。

几乎每张表都会有这些字段,而且在你编写 CRUD 操作代码的时候,都需要对这些字段进行赋值或修改。从我个人感觉,这会带来至少两点问题:第一、代码重复率较高,第二、容易出错,一不小心忘了修改某个字段,测试人员就会给你提个 bug。

所以,我就通过 AOP 的思想进行了统一处理。

实体封装

既然所有的表都有这些字段,实体设计的时候就可以通过继承的方式进行统一管理。

1. 定义 BaseEntity

public class BaseEntity implements Serializable {
    /**
     * 创建人id
     */
    private Long creatorId;

    /**
     * 创建人
     */
    private String createdBy;

    /**
     * 创建时间
     */
    private Date createdAt;

    /**
     * 修改人id
     */
    private Long updaterId;

    /**
     * 修改人
     */
    private String updatedBy;

    /**
     * 修改时间
     */
    private Date updatedAt;
}

2. 定义业务Entity:

public class Goods extends BaseEntity {

}

自定义 AOP

1. 自定义注解,用来标识 某个接口是 新增还是修改操作。

@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MetaInfoAnnotation {
    OperateTypeEnum value();
}

2. 自定义的 OperateTypeEnum 

public enum OperateTypeEnum {
    ADD,
    DELETE,
    UPDATE;
}

3. 自定义 aop 操作

public class MetaInfoAop {

    @Pointcut("@annotation(com.xx.aop.MetaInfoAnnotation))")
    public void doSet(){}

    /**
     * 环绕增强,相当于MethodInterceptor
     */
    @Around("doSet()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        Object res = null;
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        MetaInfoAnnotation annotation = signature.getMethod().getAnnotation(MetaInfoAnnotation.class);
        OperateTypeEnum value = annotation.value();
        Object[] args = joinPoint.getArgs();
        if (args.length > 0) {
            BaseEntity arg = (BaseEntity) args[0];
            Date now = new Date();
            UserSessionMsg sessionUser = OperateSessionUserUtil.getUserSessionMsg();
            UserInfo user = sessionUser.getUserInfo();
            Long userId = user.getUserId();
            String userName = user.getRealName();
            if (value == OperateTypeEnum.ADD) {
                arg.setCreatorId(userId);
                arg.setCreatedBy(userName);
                arg.setCreatedAt(now);
                arg.setUpdaterId(userId);
                arg.setUpdatedBy(userName);
                arg.setUpdatedAt(now);
            }

            if (value == OperateTypeEnum.UPDATE || value == OperateTypeEnum.DELETE) {
                arg.setUpdaterId(userId);
                arg.setUpdatedBy(userName);
                arg.setUpdatedAt(now);
            }

        }

        return joinPoint.proceed(args);
    }
}

使用

在 controller 中使用,以 添加操作为例:

@RestController
@RequestMapping("/goods")
public class GoodsController {

    @MetaInfoAnnotation(value = OperateTypeEnum.ADD)
    @PostMapping("/save")
    public ResponseBean save(@RequestBody Goods goods){
        try {
            goodsService.add(goods);
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        return new ResponseBean(true, "保存成功",  ResponseCode.SUCCESS);
    }

通过以上操作,你开发新业务时,就不用再关心实体元数据,专心处理你的核心业务字段即可。


 如果觉得还不错的话,关注、分享、在看(关注不失联~), 原创不易,且看且珍惜~

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

【非典型Coder】

赏个鸡腿吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值