Używam weryfikacji JPA 2.0 / Hibernate do sprawdzania poprawności moich modeli. Mam teraz sytuację, w której połączenie dwóch pól musi zostać sprawdzone:
public class MyModel {
public Integer getValue1() {
//...
}
public String getValue2() {
//...
}
}
Model jest nieważne , gdy oba getValue1()
i getValue2()
są null
i ważne inaczej.
Jak mogę przeprowadzić tego rodzaju walidację za pomocą JPA 2.0 / Hibernate? W przypadku prostej @NotNull
adnotacji oba metody pobierające muszą mieć wartość różną od null, aby przejść weryfikację.
java
jpa
jpa-2.0
bean-validation
Daniel Rikowski
źródło
źródło
Odpowiedzi:
W przypadku walidacji wielu właściwości należy użyć ograniczeń na poziomie klasy. Z Bean Validation Sneak Peek, część II: niestandardowe ograniczenia :
źródło
TYPE
iRUNTIME
powinien być zastąpionyElementType.TYPE
iRetentionPolicy.RUNTIME
odpowiednio.import static java.lang.annotation.ElementType.*;
iimport static java.lang.annotation.RetentionPolicy.*;
Aby pracować poprawnie z Bean Validation , na przykład przewidzianej w Pascalu Thivent za odpowiedź może zostać przepisany w następujący sposób:
@ValidAddress public class Address { @NotNull @Size(max = 50) private String street1; @Size(max = 50) private String street2; @NotNull @Size(max = 10) private String zipCode; @NotNull @Size(max = 20) private String city; @Valid @NotNull private Country country; // Getters and setters }
public class Country { @NotNull @Size(min = 2, max = 2) private String iso2; // Getters and setters }
@Documented @Target(TYPE) @Retention(RUNTIME) @Constraint(validatedBy = { MultiCountryAddressValidator.class }) public @interface ValidAddress { String message() default "{com.example.validation.ValidAddress.message}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
public class MultiCountryAddressValidator implements ConstraintValidator<ValidAddress, Address> { public void initialize(ValidAddress constraintAnnotation) { } @Override public boolean isValid(Address address, ConstraintValidatorContext constraintValidatorContext) { Country country = address.getCountry(); if (country == null || country.getIso2() == null || address.getZipCode() == null) { return true; } switch (country.getIso2()) { case "FR": return // Check if address.getZipCode() is valid for France case "GR": return // Check if address.getZipCode() is valid for Greece default: return true; } } }
źródło
isoA2Code
jest przechowywana wCountry
tabeli DB . Czy to dobry pomysł, aby wywołać DB stąd? Chciałbym również połączyć je po walidacji, ponieważAddress
belongs_to
aCountry
i chcę, abyaddress
wpis zawierałcountry
klucz obcy tabeli. Jak powiązałbym kraj, z którym należy się zwrócić?@ValidAddress
adnotację w obiekcie Country, otrzymaszNo validator could be found for constraint 'com.example.validation.ValidAddress' validating type 'com.example.Country'
wyjątek.Niestandardowy walidator na poziomie klasy jest dobrym rozwiązaniem, jeśli chcesz pozostać przy specyfikacji walidacji fasoli, na przykład tutaj .
Jeśli z przyjemnością korzystasz z funkcji Hibernate Validator, możesz użyć @ScriptAssert , który jest dostępny od wersji Validator-4.1.0.Final. Exceprt z JavaDoc:
Przykład:
@ScriptAssert(lang = "javascript", script = "_this.value1 != null || _this != value2)") public class MyBean { private String value1; private String value2; }
źródło