2014-11-19 14 views
7

Mam komponent bean, w którym definiuję wiele adnotacji sprawdzania poprawności dla każdego pola, np.Jak wykonać walidację sprawdzania poprawności Hibernuj na pierwszym naruszeniu pola?

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

ja spotkałem dwa jeden problem, że nie mogę rozwiązać w łatwy sposób.

  1. Kolejność sprawdzania określonych adnotacji dla każdego pola jest losowa, tj. Nie występuje w kolejności, w której są zdefiniowane adnotacje. Uważam, że @GroupSequence nie pomoże, ponieważ definiuje tylko sekwencję sprawdzania poprawności grupy, a nie sekwencję adnotacji. Jak poprawnie skomentowano @Tom, naruszenia są zgłaszane jako ustawione, co oznacza, że ​​nie ma odwzorowania 1: 1 między kolejnością wykonywania adnotacji a zgłoszonymi naruszeniami.
  2. Chcę unieważnić tylko jedną regułę dla każdego pola, tzn. Jeśli nie pasuje do wzorca, nie należy sprawdzać, czy wartość jest równa> = 1. Obecnie, jeśli ustawiona jest mojaField na "abc", będzie raportować zarówno @Pattern, jak i @ Min. Naruszenia. Ustawienie właściwości failFast walidatora na true nie pomaga, ponieważ używam tej samej instancji sprawdzania poprawności do sprawdzania poprawności wszystkich pól w moim komponencie bean i przestanie sprawdzać poprawność innych pól, gdy tylko napotkane zostanie pierwsze naruszenie całego komponentu bean.

Edytuj. Próbowałem zaimplementować niestandardowe ograniczenie złożenia za pomocą @ReportAsSingleViolation. Problem polega na tym, że zgłosi tę samą wiadomość dla wszystkich naruszeń związanych ze składem. To nie jest to, czego potrzebuję.

Sugestie, proszę?

+0

Czy jesteś pewien, że kolejność sprawdzania jest losowa? O ile pamiętam, walidator zwraca 'Set' z' ConstraintViolation'. Ten zestaw nie ma określonej kolejności. Tak więc nie ma żadnego związku między poleceniem walidacji a kolejnością zgłaszanych naruszeń. – Tom

+0

@ Tom OK, może są wykonywane w zdefiniowanej kolejności. Ale masz rację, chyba że Set interfece jest wspierany przez jedną z uporządkowanych zestawów implementacji, nie może być mapowania 1: 1 między kolejnością wykonywania i kolejnością zgłaszanych naruszeń. Co oznacza, że ​​to, czego tak naprawdę szukam, jest odpowiedzią na moje drugie pytanie. – davidgale

+0

Można to sprawdzić za pomocą debuggera i sprawdzić, która implementacja "zestawu" jest tam używana. Może to być 'LinkedHashSet', ale zakładam, że to po prostu normalny' HashSet'. Cóż, w drugiej części: obecnie widzę tylko jedno brudne rozwiązanie: napisz swój własny walidator dla każdego pola. Mam jednak nadzieję, że ktoś inny (który ma więcej doświadczenia z Hibernate Validator) ma o wiele lepszy pomysł :). – Tom

Odpowiedz

1

Można było compose your constraints. Ale dzięki temu otrzymasz tylko jeden błąd dla dowolnego z określonych ograniczeń, nie wiesz, czy jest to dopuszczalne w twoim przypadku użycia.

+0

Niedopuszczalne. – davidgale

+1

Wtedy @davidgale być może powinieneś o tym wspomnieć w swoim pytaniu. Uważam, że musisz napisać własną implementację ograniczenia/walidatora. –

4

Powinno być możliwe stworzenie zachowanie chcesz osiągnąć stosując kombinację validation groups oraz w pełni zdefiniowane validation group sequence

Cytując JSR-349 (aka. BeanValidation 1.1) spec, paragraph 4.4.2

tworzenie grupy jest zdefiniowana w punkt 4.6; jeśli jedna z grup przetworzonych w sekwencji generuje jedno lub więcej naruszeń ograniczeń, grupy następujące po sekwencji nie mogą być przetwarzane. Zapewnia to ocenę zestawu ograniczeń tylko wtedy, gdy inny zestaw ograniczeń jest poprawny.
podświetlanie przez mnie

ta powinna być stosunkowo łatwe, przechodząc przez 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; 
} 

z Second i Third zdefiniowany jako prostych markerów interfejsy powinno załatwić sprawę. Pamiętaj, że to nie sprawdza wszystkich pól do czasu pierwszego naruszenia ograniczenia, ale tylko do pierwszego ogólnego naruszenia.

Oznacza to, że niektóre z pól mogą stać się nieprawidłowe po naprawieniu innych pól.

Jeśli wszystko inne zawiedzie, nadal można ponownie wdrożyć komponenty behawioralne, dostawcę sprawdzania poprawności. Powinieneś być w stanie dostarczyć swoją realizację ConstraintValidatorContext stosując validation.xml

Należy pamiętać ci, że mieć zerwać umowę ConstraintValidatorContext.ConstraintViolationBuilder:

Aby utworzyć ConstraintViolation, jeden musi wywoływać jedną z metod addConstraintViolation() dostępnych w jednym z interfejsów płynnego interfejsu API.

Jeśli inny sposób nazywa po addConstraintViolation() na ConstraintViolationBuilder i powiązany z nim przedmioty IllegalStateException jest podniesiony.

0

Do tej pory trzeba użyć rozwiązania @GroupSequence opisanego w innej odpowiedzi. Jednak zespół Hibernate szuka rozwiązania z nadchodzącymi funkcjami JDK, a nawet pracuje z programistami OpenJDK: BVAL-248

Powiązane problemy