实现公共字段自动填充(Mybatis-plus)(AOP + 反射)

方法一:Mybatis-plus实现

步骤一:在实体类的属性上使用@TableField注解指定自动填充的策略

参数可为

1:@TableField(fill = FieldFill.INSERT)   时机:在插入数据的时候

2:@TableField(fill = FieldFill.UPDATE)  时机:在更新数据的时候

3:@TableField(fill = FieldFill.INSERT_UPDATE)  时机:在插入或更新数据的时候

示例如图:

步骤二: 创建一个类,实现(implements)MetaObjectHandler接口并重写insertFill(MetaObject metaObject)updateFill(MetaObject metaObject)方法。

这两个方法分别对应着属性自动填充的时机。插入数据的时候,和更新数据的时候

接着,在重写的方法里写语句:metaObject.setValue(String name, Object value);第一个参数对应着实体类属性的名称,第二个参数对应着属性自动填充的

示例如图:

最后记得在类上面加上@Component注解,把这个类交给Spring管理。

方法二:(AOP + 反射)实现

步骤一:自定义枚举FieldFill,定义数据库操作类型
public enum FieldFill {

    INSERT, //插入操作

    UPDATE; //更新操作

    private FieldFill() {
    }
}

步骤二:自定义注解AutoFill,后续为被该注解标记的方法执行自动填充

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface TableField {
   FieldFill fill();
}

步骤三:定义通知类,切入点,切面,通知

@Aspect
@Component
public class AutoFillAspect {
    //定义切入点
    @Pointcut("execution(* com.aurora.aop.mapper.*.*(..)) && @annotation(com.aurora.aop.annotation.TableField)")
    public void autoFillPoinCut(){}

    //定义通知,因为insert和update之前,故前置通知
    @Before("autoFillPoinCut()")
    public void autoFill(JoinPoint joinPoint){

        //获取到当前被拦截的方法上的数据库操作类型
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        TableField tableField = signature.getMethod().getAnnotation(TableField.class);
        FieldFill fillType = tableField.fill();

        //获取到当前被拦截的方法的方法参数,即实体类
        Object[] args = joinPoint.getArgs();
        Object entity = args[0];
        LocalDateTime now = LocalDateTime.now();

        //根据不同的操作类型
        if (fillType == FieldFill.INSERT) {
            //为公共字段赋值
            try {
                Method setCreatTime = entity.getClass().getDeclaredMethod("setCreatTime",
                        LocalDateTime.class);
                setCreatTime.invoke(entity,now);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }


    }
}

 以实体类User举例:

@Data
public class User {
    private String username;
    private String password;
    private LocalDateTime creatTime;
}

UserMapper:

@Mapper
public interface UserMapper {

    @TableField(fill = FieldFill.INSERT)
    @Insert("insert into user (username, password, creat_time) values (#{username}, #{password}, #{creatTime})")
    void insert(User user);
}

在insert方法中添加我们自定义的注解@TableField(fill = FieldFill.INSERT),当运行到这个方法之前,在我们的通知中会把参数中的user的公共字段creatTime字段赋值。

最后测试用例:

@SpringBootTest
class AopApplicationTests {

    @Autowired
    private UserMapper userMapper;
    @Test
    void testAOP() {
        User user = new User();
        user.setUsername("aop");
        user.setPassword("666666666");
        userMapper.insert(user);
    }
}

运行结果:

可以看到,我们并没有为User中的creatTime属性赋值,但是实现了字段填充! 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值