我知道hibernate验证器支持TYPE_USE
注释:虽然它没有自己定义,但它允许你定义和使用自定义注释。
我可以正确定义和验证这样的注释(代码很快),但后来我想将错误映射到用于向用户显示错误的路径。
然后给出以下样本
public class SampleTest {
private final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
public static class LimitedSizeStringValidator implements ConstraintValidator<LimitedSize, String> {
private LimitedSize constraint;
@Override
public void initialize(LimitedSize constraintAnnotation) {
this.constraint = constraintAnnotation;
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
String s = Ensure.notNull(value);
return s.length() >= constraint.min() &&
s.length() <= constraint.max();
}
}
@Retention(RUNTIME)
@Documented
@Target({TYPE_USE})
@Constraint(validatedBy = {LimitedSizeStringValidator.class})
public @interface LimitedSize {
String message() default "{javax.validation.constraints.Size.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
int min() default 0;
int max() default Integer.MAX_VALUE;
}
private static class TestBean {
@Valid
private Collection<@LimitedSize(max = 3) String> strings = new ArrayList<>();
@Valid
private Collection<InnerBean> beans = new ArrayList<>();
}
private static class InnerBean {
@Min(3)
private final int value;
private InnerBean(int value) {
this.value = value;
}
}
@Test
public void testBeanInvalid() {
TestBean testBean = new TestBean();
assertThat(validator.validate(testBean)).isEmpty();
testBean.strings.add("ok");
testBean.strings.add("ok2");
testBean.beans.add(new InnerBean(4));
assertThat(validator.validate(testBean)).isEmpty();
testBean.strings.add("not_ok");
testBean.beans.add(new InnerBean(2));
Set<ConstraintViolation<TestBean>> violations = validator.validate(testBean);
assertThat(violations).hasSize(2);
StreamSupport.stream(violations.spliterator(), false)
.forEach(v -> {
System.out.println(v.getPropertyPath());
System.out.println(v.getMessage());
v.getPropertyPath().forEach(p -> System.out.print("'" + p.getName() + (p.getIndex() != null ? "[" + p.getIndex() + "]" : "") + "' -> "));
System.out.println();
});
}
}
我想在
这样的对象中映射错误errors: [
["beans", "1", "value"],
["strings", "2"]
]
在我的示例中,我目前的方法是导航违规路径(http://docs.oracle.com/javaee/7/api/javax/validation/ConstraintViolation.html#getPropertyPath--),该路径适用于第一种情况,但第二种情况失败(我无法找到检索索引的方法)失败的对象)。我认为原因是在hibernate-validator中实现javax.validation.Path.PropertyNode(我目前使用的是5.2.4.Final
版本,代码与链接的5.2.1.Final
中的代码相同。供参考:< / p>
@Override
public final Integer getIndex() {
if ( parent == null ) {
return null;
}
else {
return parent.index;
}
}
使用TYPE_USE
这种方法在我看来不行,因为失败的对象是一个叶子,因此没有子节点可以从中检索索引。
很好,javax.validation.Path
的hibernate实现覆盖了toString
方法,violation.getPropertyPath().toString()
是beans[1].value
和strings[2]
(在上面的示例代码中)
那么,对于问题:我的导航方法是错误的还有另一种方法从ConstraintViolation
中提取这样的映射?或者这是hibernate开发人员的功能请求(我可以在TYPE_USE
注释之前看到他们实现的getIndex
方法完全正常吗?
感觉很奇怪我是第一个遇到这个问题的人(我试图google并找不到任何相关内容,最接近的是:https://github.com/hibernate/hibernate-validator/pull/441)所以我想知道这个错误是我的而不是一个休眠限制
答案 0 :(得分:2)
我同意应该为该值设置索引,并认为您在Hibernate Validator中发现了一个问题。你能否在我们的JIRA tracker?
中打开一个问题顺便说一下。从Bean Validation 2.0开始,TYPE_USE级别约束的概念将被标准化。因此,此区域可能会有更多更改,特别是我想知道该节点应该具有哪些Kind
(目前它PROPERTY
似乎有问题。)