相同属性上的不同Hibernate验证注释

时间:2010-10-13 16:13:01

标签: hibernate hibernate-validator

我在bean中的属性上使用了两个验证注释:

@NotEmpty(message = "{name.required}")
@Pattern(regex = "^([A-Za-z0-9]{2,}(\\-[a-zA-Z0-9])?)$", message = "{invalid.name}")
private String name;

如果我将名称留空,我得到了两个错误,但我只想要第一条错误消息 (如果出现第一个条件,则显示其错误消息,然后跳过第二个条件)。

2 个答案:

答案 0 :(得分:4)

  

如果出现第一个条件,则显示其错误消息,然后跳过第二个条件

这可以通过创建复合约束并使用@ReportAsSingleViolation元约束进行注释来完成。

<强> UserName.java

@ReportAsSingleViolation
@NotEmpty
@Pattern(regexp="^([A-Za-z0-9]{2,}(\\-[a-zA-Z0-9])?)$")
@Constraint(validatedBy = {})
public @interface UserName {
    String message() default "invalid userName!";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

参考3.2. Constraint composition

答案 1 :(得分:0)

接受的答案并不像您期望的那样有效。只有当您想在整个组合链中列出 ALL 错误时,才能确保约束合成。如果您想提前退出第一个验证错误,它就无法工作。

@ReportAsSingleViolation的文档说忽略每个个人撰写约束的错误报告

使用接受示例

@ReportAsSingleViolation
@NotEmpty
@Pattern(regexp="^([A-Za-z0-9]{2,}(\\-[a-zA-Z0-9])?)$")
@Constraint(validatedBy = {})
public @interface UserName {
    String message() default "invalid userName!";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

这意味着您将获得UserName注释的默认消息错误,即&#34;无效的用户名!&#34;即使@NotEmpty首先失败......

我必须说我对java bean验证实现者的设计有多糟糕感到震惊。如果您返回完全不相关的消息,则完成组合验证是完全没有意义的。它应该首先失败并返回实际失败的验证的相应错误!无论如何,如果没有大规模的丑陋黑客,就没有办法做到这一点。这样一个简单的验证任务变成了一场噩梦。 0_o

我的解决方案是不进行验证,只需创建1个验证并自行完成。它不是DRY,但它至少是简单的。

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PasswordValidator.class)
public @interface Password {
    String message() default "{com.example.Password.message}";

    Class<?>[] groups() default { };

    Class<? extends Payload>[] payload() default { };
}



public class PasswordValidator implements ConstraintValidator<Password, String> {
    private Pattern twoDigitsPattern;

    public void initialize(Password constraint) {
        twoDigitsPattern = Pattern.compile("(.*[\\d]){2}");
    }

    public boolean isValid(String password, ConstraintValidatorContext context) {
        context.disableDefaultConstraintViolation();

        if (password == null) {
            context.buildConstraintViolationWithTemplate("{javax.validation.constraints.NotNull.message}")
                    .addConstraintViolation();
            return false;
        }

        if (password.length() < 5 || password.length() > 10) {
            context.buildConstraintViolationWithTemplate("must be between 5 to 10 characters")
                    .addConstraintViolation();
            return false;
        }

        if (!twoDigitsPattern.matcher(password).matches()) {
            context.buildConstraintViolationWithTemplate("must contain 2 digits between [0-9]").addConstraintViolation();
            return false;
        }

        return true;
    }

}