SpringBoot操作MySQL数据库实现表公共字段自动填充
内容纲要

背景

平时项目的需求上少不了一些对数据库表的CRUD,为了数据的安全和管理,各个表中难免会存在一些公共的字段如create_time create_user update_time updete_user 来对各个操作进行追踪管理,如果每次更新字段都需要我们在service层进行操作的话,代码出现冗余,且如果后期表字段出现变更,维护成本也无法保证。这时遍催生了新的需求,就是将这些公共字段实现自动填充。

实现思路

使用AOP切面编程来实现功能增强!来完成对公共字段的自动填充!
实现步骤:
1.自定义注解 AutoFill,用于标识需要进行公共字段自动填充的方法
2.自定义切面类AutoFillAspect,统一拦截加入了AutoFill注解的方法,通过反射为公共字段赋值
3.在Mapper的方法上加入AutoFill注解
其主要技术点在:枚举、注解、AOP、反射

具体实现

因为这些自动填充字段更新的操作只涉及到插入(INSERT)和更新(UPDATE),所以需要先定义枚举类:

/**
 * @description 数据库操作类型
 * @author LoungeXi
 */
public enum OperationType {
    /**
     * 更新操作
     */
    UPDATE,

    /**
     * 插入操作
     */
    INSERT
}

自定义注解AutoFill:

/**
 * @description 自定义注解,用于标识某个方法需要进行功能字段自动填充处理
 * @author LoungeXi
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {
    //数据库操作类型:UPDATE INSERT
    OperationType value();
}

定义切面类:

/**
 * @author LoungeXi
 * @description 自定义切面类 实现公共字段自动填充
 */
@Aspect
@Component
@Slf4j
public class AutoFillAspect {

    /**
     * @description 切入点
     * @author LoungeXi
     * @params * @param
     */
    @Pointcut("execution(* cn.loungexi.mapper.*.*(..)) && @annotation(cn.loungexi.annotation.AutoFill)") //路径换成自己本地路径
    public void autoFillPointCut() {}

    /**
     * @description 前置通知,在通知中对公共字段进行赋值
     * @author LoungeXi
     * @params * @param
     */
    @Before("autoFillPointCut()")
    public void autoFill(JoinPoint joinPoint) throws Exception {
        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 {
                // 获取方法 AutoFillConstant.SET_CREATE_TIME是实体类的set方法名 下面类似
                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 Exception(e);
            }
        }else if (operationType == OperationType.UPDATE){
            // 为两个公共字段赋值
            try {
                // 获取方法 AutoFillConstant.SET_UPDATE_TIME是实体类的set方法名 下面类似
                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 (NoSuchMethodException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

在Mapper接口的方法上加入 AutoFill 注解,如:

/**
 * @author LoungeXi
 * @description 分类Mapper接口
 */
@Mapper
public interface CategoryMapper {
    @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(value = OperationType.INSERT)
    void insert(Category category) ;

    @AutoFill(value = OperationType.UPDATE)
    void update(Category category);
}

至此需求完成。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇
隐藏
变装