如何使Hibernate Validator在第一次字段违规时停止验证?

时间:2014-11-19 13:34:39

标签: java hibernate validation

我有一个bean,我为每个字段定义了多个验证注释,例如

@NotEmpty
@Pattern(regexp="(\\-?\\d)+")
@Min(value=1)
String myField;

我遇到了两个一个我无法轻易解决的问题。

  1. 每个字段的指定注释的验证顺序是随机的,即不按照定义注释的顺序发生。我相信@GroupSequence不会有帮助,因为它只定义了组验证序列,而不是注释序列。 正如@Tom正确评论的那样,违规被报告为Set,这意味着注释的执行顺序与报告的违规之间没有1:1的映射。
  2. 我想要为每个字段仅使一个规则无效,即如果它与模式不匹配,则不要尝试检查该值是否为> = 1.目前,如果将myField设置为" abc"它会报告@Pattern和@Min违规行为。将验证器的failFast属性设置为true无济于事,因为我使用相同的验证器实例来验证我的bean中的所有字段,并且一旦遇到整个bean的第一次违规,它将停止验证其他字段
  3. 编辑。我尝试使用@ReportAsSingleViolation实现自定义复合约束。问题是它将为组合中涉及的所有违规报告相同的消息。这不是我需要的。

    建议,拜托?

3 个答案:

答案 0 :(得分:6)

应该可以使用validation groups和完全定义的validation group sequence

的组合来创建您想要实现的行为

引自JSR-349 (aka. BeanValidation 1.1) spec, paragraph 4.4.2

  

处理组在第4.6节中定义;如果序列中处理的其中一个组生成一个或多个约束违规,则不得处理序列中的组。这样可确保仅在另一组约束为有效的。
  由我强调

这应该相对容易,按Group Sequence Example

进行
@GroupSequence({YourClass.class, Second.class, Third.class})
public class YourClass {
    @NotNull
    @Pattern(regexp="(\\-?\\d)+", groups=Second.class)
    @Min(value=1, groups=Third.class)
    String myField;
}

SecondThird定义为简单的标记接口应该可以解决问题。请注意,在第一次违反约束之前,这不会验证所有字段,而是直到第一次完全违规。

这意味着在修复其他字段后,您的某些字段可能变得无效'违规。

如果所有其他方法都失败了,您仍然可以重新实现行为组件,验证提供程序。 您应该能够使用validation.xml

提供自己的ConstraintValidatorContext实现

请注意您 违反ConstraintValidatorContext.ConstraintViolationBuilder的合同:

  

要创建ConstraintViolation,必须调用其中一个   addConstraintViolation()方法在其中一个接口中可用   流畅的API。

     

如果在addConstraintViolation()之后调用另一个方法   ConstraintViolationBuilder或其任何关联对象   IllegalStateException被提出。

答案 1 :(得分:1)

你可以compose your constraints。但是,对于任何指定的约束,您只会得到一个错误,不确定在您的用例中是否可接受。

答案 2 :(得分:0)

到目前为止,您必须使用其他答案中描述的@GroupSequence解决方案。但是,Hibernate团队正在寻找具有JDK即将推出的功能的解决方案,甚至与OpenJDK开发人员合作:BVAL-248