簡體   English   中英

休眠驗證器中的 TYPE_USE 注釋

[英]TYPE_USE annotation in hibernate validator

我知道 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.4.Final ,代碼看起來與鏈接的5.2.1.Final的相同。供參考:

@Override
public final Integer getIndex() {
    if ( parent == null ) {
        return null;
    }
    else {
        return parent.index;
    }
}

使用TYPE_USE這種方法在我看來是行不通的,因為失敗的對象是葉子,因此沒有子節點可以從中檢索索引。

很不錯, javax.validation.Path休眠實現覆蓋了toString方法,這樣的方法javax.validation.Path violation.getPropertyPath().toString()beans[1].valuestrings[2] (在上面的示例代碼中)。

所以,對於問題:我的導航方法是錯誤的,還有另一種方法可以從ConstraintViolation提取這樣的映射嗎? 或者這是對休眠開發人員的功能請求(我可以看到在TYPE_USE注釋getIndex他們實現的getIndex方法完全沒問題?

只是感覺很奇怪我是第一個遇到這個問題的人(我試圖用谷歌搜索並找不到任何相關的東西,最接近的是: https : //github.com/hibernate/hibernate-validator/pull/441 )所以我想知道錯誤是否是我的而不是休眠限制

我同意應該為該值設置索引,並認為您在 Hibernate Validator 中發現了一個問題。 你能在我們的JIRA 跟蹤器中打開一個問題嗎?

順便提一句。 TYPE_USE 級別約束的概念將從 Bean Validation 2.0 開始標准化。 所以這個領域可能會有更多的變化,特別是我想知道那個節點應該有什么Kind (目前它是PROPERTY似乎有問題)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM