自定义注解校验数据库字段是否重复

本文介绍了如何创建一个自定义注解(@UniqueCheck)用于在运行时进行数据校验,该注解应用于实体类的字段,配合约束验证器(UniqueCheckValidator)检查字段在数据库中的唯一性。当需要校验多个字段时,可以通过逗号分隔字段名。此外,通过在接口方法上添加@Validated注解来触发校验过程。

1-新增一个注解

@Documented //用来文档的
@Target(ElementType.TYPE) //作用目标:Class, interface (including annotation type), or enum declaration
@Retention(RetentionPolicy.RUNTIME) //生命周期:运行时
@Constraint(validatedBy = UniqueCheckValidator.class) //限定自定义注解使用的方法
public @interface UniqueCheck {

    //需要校验的字段
    String filedName();

    //默认提示的文本
    String message() default "字段已经存在";

    //分组校验
    Class<?>[] groups() default {};

    //这个不知道干嘛用的
    Class<? extends Payload>[] payload() default {};
}

2-定义处理校验逻辑的类

public class UniqueCheckValidator implements ConstraintValidator<UniqueCheck, Object> {

    private String fieldName;
    private Long id;

    @Override
    public void initialize(UniqueCheck constraintAnnotation) {
        this.fieldName = constraintAnnotation.filedName();
    }

    @Override
    public boolean isValid(Object o, ConstraintValidatorContext context) {
        String message = check(o);
        if (ObjectUtil.isNull(message)){
            return true;
        }
        context.disableDefaultConstraintViolation();
        context.buildConstraintViolationWithTemplate(message).addConstraintViolation();
        return false;
    }

    @SneakyThrows
    private String check(Object o){
        //需要校验的字段
        String[] split = fieldName.split(",");

        Class<?> aClass = o.getClass();
        String beanName = aClass.getSimpleName().toLowerCase() + "Mapper";
        BaseMapper mapper = (BaseMapper) SpringUtils.getBean(beanName);

        Map<String, Object> paramsMap = new LinkedHashMap<>();
        Field id = aClass.getDeclaredField("id");
        id.setAccessible(true);
        Object idValue = id.get(o);
        Optional.ofNullable(id).ifPresent( i ->{
            this.id = (Long) idValue;
        });
        for (String checkField : split) {
            Field field = aClass.getDeclaredField(checkField);
            field.setAccessible(true);
            Object fieldValue = field.get(o);
            //获取注解上的值(数据库字段名称)
            String dbValue = field.getAnnotation(TableField.class).value();
            paramsMap.put(dbValue, fieldValue);
        }
        return spliceWrapper(paramsMap,mapper);
    }

    //拼接参数
    private String spliceWrapper(Map<String, Object> paramsMap, BaseMapper mapper){
        if (paramsMap.size() < 1){
            //没有需要校验的字段
            return null;
        }

        QueryWrapper<Object> wrapper = new QueryWrapper<>();
        Optional.ofNullable(id).ifPresent(o -> {
            wrapper.ne("id",id);
        });

        for (Map.Entry<String, Object> entry : paramsMap.entrySet()) {
            wrapper.eq(entry.getKey(),entry.getValue());
            Long count = mapper.selectCount(wrapper);
            if (count > 0){
                return entry.getValue() + "已经存在";
            }
            wrapper.clear();
            Optional.ofNullable(id).ifPresent(o -> {
                wrapper.ne("id",id);
            });
        }
        return null;
    }
}

3-将注解加在所需校验的实体类上

@Data
@TableName("t_user")
@UniqueCheck(filedName = "username")
public class User implements Serializable {

  @TableId(type = IdType.AUTO)
  private Long id;

  private String nickname;

  @TableField("username")
  private String username;

}

如果需要校验多个字段,改成@UniqueCheck(filedName = "username,nickname"),使用逗号隔开来,需要注意的是,需要校验的字段需要加上@TableField注解,这样才能被校验类获取到数据库表字段的值。

4-在接口处加上@Validated注解

@RequestMapping("add")
public Result add(@RequestBody @Validated User user){
    userService.add(user);
    return Result.success("新增成功");
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值