Cross field validation with Hibernate Validator (JSR 303)

前端 未结 15 1752
渐次进展
渐次进展 2020-11-22 02:37

Is there an implementation of (or third-party implementation for) cross field validation in Hibernate Validator 4.x? If not, what is the cleanest way to implement a cross fi

15条回答
  •  梦如初夏
    2020-11-22 02:52

    Solution realated with question: How to access a field which is described in annotation property

    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Match {
    
        String field();
    
        String message() default "";
    }
    

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Constraint(validatedBy = MatchValidator.class)
    @Documented
    public @interface EnableMatchConstraint {
    
        String message() default "Fields must match!";
    
        Class[] groups() default {};
    
        Class[] payload() default {};
    }
    

    public class MatchValidator implements  ConstraintValidator {
    
        @Override
        public void initialize(final EnableMatchConstraint constraint) {}
    
        @Override
        public boolean isValid(final Object o, final ConstraintValidatorContext context) {
            boolean result = true;
            try {
                String mainField, secondField, message;
                Object firstObj, secondObj;
    
                final Class clazz = o.getClass();
                final Field[] fields = clazz.getDeclaredFields();
    
                for (Field field : fields) {
                    if (field.isAnnotationPresent(Match.class)) {
                        mainField = field.getName();
                        secondField = field.getAnnotation(Match.class).field();
                        message = field.getAnnotation(Match.class).message();
    
                        if (message == null || "".equals(message))
                            message = "Fields " + mainField + " and " + secondField + " must match!";
    
                        firstObj = BeanUtils.getProperty(o, mainField);
                        secondObj = BeanUtils.getProperty(o, secondField);
    
                        result = firstObj == null && secondObj == null || firstObj != null && firstObj.equals(secondObj);
                        if (!result) {
                            context.disableDefaultConstraintViolation();
                            context.buildConstraintViolationWithTemplate(message).addPropertyNode(mainField).addConstraintViolation();
                            break;
                        }
                    }
                }
            } catch (final Exception e) {
                // ignore
                //e.printStackTrace();
            }
            return result;
        }
    }
    

    And how to use it...? Like this:

    @Entity
    @EnableMatchConstraint
    public class User {
    
        @NotBlank
        private String password;
    
        @Match(field = "password")
        private String passwordConfirmation;
    }
    

提交回复
热议问题