JPA 2.0 / Hibernate検証を使用してモデルを検証しています。2つのフィールドの組み合わせを検証する必要がある状況になりました。
public class MyModel {
public Integer getValue1() {
//...
}
public String getValue2() {
//...
}
}
との両方の場合、モデルは無効getValue1()
でgetValue2()
ありnull
、そうでない場合は有効です。
JPA 2.0 / Hibernateでこの種の検証を実行するにはどうすればよいですか?単純な@NotNull
注釈の場合、検証に合格するには両方のゲッターがnull以外である必要があります。
複数のプロパティの検証では、クラスレベルの制約を使用する必要があります。ビーン検証スニークピーク部分II:カスタム制約:
クラスレベルの制約
複数のプロパティにまたがる制約を適用したり、複数のプロパティに依存する制約を表現したりする機能について懸念を表明している方もいます。古典的な例は住所の検証です。アドレスには複雑なルールがあります。
- 通りの名前はやや標準的で、確かに長さの制限がなければなりません
- 郵便番号の構造は完全に国に依存します
- 多くの場合、都市は郵便番号に関連付けることができ、いくつかのエラーチェックを実行できます(検証サービスにアクセスできる場合)。
- これらの相互依存性のため、単純なプロパティレベルの制約は法案に適合します
Bean Validation仕様によって提供されるソリューションは2つあります。
- グループとグループシーケンスを使用して、制約のセットを他の制約のセットの前に強制的に適用する機能を提供します。この件については、次のブログエントリで説明します。
- クラスレベルの制約を定義することができます
クラスレベルの制約は、プロパティではなくクラスに適用される通常の制約(注釈/実装の組み合わせ)です。つまり、クラスレベルの制約は、プロパティ値ではなくオブジェクトインスタンスをで受け取ります
isValid
。@AddressAnnotation public class Address { @NotNull @Max(50) private String street1; @Max(50) private String street2; @Max(10) @NotNull private String zipCode; @Max(20) @NotNull String city; @NotNull private Country country; ... } @Constraint(validatedBy = MultiCountryAddressValidator.class) @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface AddressAnnotation { String message() default "{error.address}"; Class<?>[] groups() default { }; Class<? extends Payload>[] payload() default { }; } public class MultiCountryAddressValidator implements ConstraintValidator<AddressAnnotation, Address> { public void initialize(AddressAnnotation constraintAnnotation) { // initialize the zipcode/city/country correlation service } /** * Validate zipcode and city depending on the country */ public boolean isValid(Address object, ConstraintValidatorContext context) { if (!(object instanceof Address)) { throw new IllegalArgumentException("@Address only applies to Address"); } Address address = (Address) object; Country country = address.getCountry(); if (country.getISO2() == "FR") { // check address.getZipCode() structure for France (5 numbers) // check zipcode and city correlation (calling an external service?) return isValid; } else if (country.getISO2() == "GR") { // check address.getZipCode() structure for Greece // no zipcode / city correlation available at the moment return isValid; } // ... } }
高度な住所検証ルールは住所オブジェクトから除外され、によって実装されてい
MultiCountryAddressValidator
ます。オブジェクトインスタンスにアクセスすることにより、クラスレベルの制約は非常に柔軟になり、複数の相関するプロパティを検証できます。順序付けはここでは方程式から除外されていることに注意してください。次の投稿でそれに戻ります。専門家グループは、さまざまな複数のプロパティサポートアプローチについて議論しました。クラスレベルの制約アプローチは、依存関係を含む他のプロパティレベルのアプローチと比較して、十分な単純さと柔軟性の両方を提供すると思います。あなたのフィードバックは大歓迎です。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加