如何让Hibernate Validator在第一次违反字段时停止验证? [英] How-to make Hibernate Validator stop validation on the first field violation?

查看:235
本文介绍了如何让Hibernate Validator在第一次违反字段时停止验证?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个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的第一个违规,它就会停止验证其他字段。 / li>

编辑。我试图用@ReportAsSingleViolation实现自定义的组合约束。问题在于它会为所有涉及构图的违规报告相同的消息。这不是我所需要的。



建议,请问?

解决方案

应该可以使用验证组和完整定义的验证组序列



引用 JSR-349(aka。BeanValidation 1.1)规范,第4.4.2节
$ b


处理组在第4.6节中定义;如果在序列中处理的一个组生成一个或多个约束违规,则必须不处理序列中的后续组。这确保只有在另一组约束是有效。

突出显示由我


这应该相对容易, 组序列示例

  @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;
}

加上第二第三个定义为简单的标记接口应该能够做到。请注意,这不会验证所有字段,直到第一次违反约束时为止,但直到第一次整体违规。



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



如果所有其他操作失败,您仍可以重新实现行为组件,即验证提供程序。
您应该能够提供您自己的实施方案 ConstraintValidatorContext 通过使用validation.xml



请注意您 strong>打破 ConstraintValidatorContext.ConstraintViolationBuilder


要创建ConstraintViolation,必须调用
addConstraintViolation()方法可用于
流畅API的接口之一。


$ b 如果另一个方法在addConstraintViolation()之后调用 / strong>在
上产生ConstraintViolationBuilder或其任何关联的对象
IllegalStateException



I have a bean where I define multiple validation annotations for each field e.g.

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

I have encountered two one problem that I cannot resolve in any easy way.

  1. Validation order of the specified annotations for each field is random i.e. do not happen in the order the annotations are defined. I believe @GroupSequence will not help since it only defines group validation sequence, not annotation sequence. As @Tom correctly commented, violations are reported as Set which means there is no 1:1 mapping between execution order of annotations and reported violations.
  2. I want to invalidate only one rule for each field i.e. if it does not match pattern do not try to check if the value is >= 1. Currently if is set myField to "abc" it will report both @Pattern and @Min violations. Setting failFast property of a validator to true does not help because I'm using the same validator instance to validate all the fields in my bean, and it will stop validating other fields as soon as the first violation for the whole bean is encountered.

Edit. I tried to implement custom composite constraint with @ReportAsSingleViolation. The problem is that it will report the same message for all violations involved in composition. This is not what I need.

Suggestions, please?

解决方案

It should be possible to create the behavior you want to achieve using a combination of validation groups and a fully defined validation group sequence

Quoting from JSR-349 (aka. BeanValidation 1.1) spec, paragraph 4.4.2

Processing a group is defined in Section 4.6 ; if one of the groups processed in the sequence generates one or more constraint violations, the groups following in the sequence must not be processed. This ensures that a set of constraint is evaluated only if another set of constraint is valid.
highlighting by me

This should be relatively easy, going by the 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;
}

with Second and Third defined as simple marker-interfaces should do the trick. Be aware that this does not validate all fields until the first constraint violation, but just until the first overall violation.

This means some of your fields may become invalid after fixing other fields' violations.

If all else fails you can still reimplement the behavioral components, your Validation Provider. You should be able to provide your own implementation of the ConstraintValidatorContext by using a validation.xml

Be aware you'd have to break the contract of ConstraintValidatorContext.ConstraintViolationBuilder:

To create the ConstraintViolation, one must call either one of the addConstraintViolation() methods available in one of the interfaces of the fluent API.

If another method is called after addConstraintViolation() on ConstraintViolationBuilder or any of its associated objects an IllegalStateException is raised.

这篇关于如何让Hibernate Validator在第一次违反字段时停止验证?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆