第13章 Bean Validation
13.1. Bean Validation リンクのコピーリンクがクリップボードにコピーされました!
Bean Validation あるいは JavaBeans Validation は、Java オブジェクトのデータのバリデーションを行うモデルです。このモデルでは、組み込みのカスタムアノテーション制約を使い、アプリケーションデータの整合性を保ちます。この仕様は「JSR 349: Bean Validation 1.1」で文書化されています。
Hibernate Validator は Bean Validation の JBoss EAP 実装であり、JSR の参照実装でもあります。
JBoss EAP は JSR 349 Bean Validation 1.1 仕様に完全準拠しています。また、Hibernate Validator によってこの仕様に追加機能が提供されます。
Bean Validation を初めて使用する場合は、JBoss EAP に同梱された bean-validation クイックスタートを参照してください。クイックスタートをダウンロードし、実行する方法については、JBoss EAP『スタートガイド』の「クイックスタートサンプルの使用」を参照してください。
JBoss EAP 7.1 には Hibernate Validator 5.3.x が含まれるようになりました。
Hibernate Validator 5.3.x の新機能
制約定義および宣言のプログラムによる API。
Hibernate Validator に、以前のリリースの API よりも一貫性の優れた新しい fluid API が導入されました。
たとえば、
ValidPassengerCountValidatorバリデーターに依存する新しいValidPassengerCount制約アノテーションを定義する場合は、この API を次のように使用できます。ConstraintMapping constraintMapping = configuration.createConstraintMapping(); constraintMapping .constraintDefinition( ValidPassengerCount.class ) .validatedBy( ValidPassengerCountValidator.class );指定のアノテーション制約に使用されるバリデーターの実装を置き換えるために使用することもできます。
詳細は、「 Hibernate Validator 5.3.0.CR1 is out」を参照してください。
制約マッピングコントリビューター。
新しい
hibernate.validator.constraint_mapping_contributorsプロパティーを使用して、複数の制約マッピングコントリビューターをカンマで区切って宣言できるようになりました。注記Hibernate Validator 5.3.x では、既存の
hibernate.validator.constraint_mapping_contributorプロパティーは継続してサポートされますが、非推奨になりました。制約の動的ペイロード。
Hibernate Validator 5.3.x では、追加のコンテキストデータを用いてカスタムの制約違反を強化することができます。制約違反を検証するコードは、文字別ベースの制約違反メッセージを解析するよりも安全にこのデータにアクセスし、解釈することができます。これは、既存の Bean Validation ペイロード機能の動的な亜種と同様です。
詳細は、「Hibernate Validator 5.3.0.Alpha1 is out」を参照してください。
電子メールの検証。
電子メールの検証方法が変更されました。電子メールのドメインは有効なドメインである必要があり、各ラベルの最大文字数は 63 文字です。
13.2. バリデーション制約 リンクのコピーリンクがクリップボードにコピーされました!
13.2.1. バリデーション制約 リンクのコピーリンクがクリップボードにコピーされました!
バリデーション制約とは、フィールド、プロパティー、Bean などの Java 要素に適用するルールのことです。制約は通常、制限を設定する際に利用する一連の属性です。定義済みの制約がありますが、カスタムの制約も作成可能です。各制約は、アノテーション形式で表されます。
Hibernate Validator 用の同梱のバリデーション制約は、Hibernate Validator の制約にリストされています。
13.2.2. Hibernate Validator の制約 リンクのコピーリンクがクリップボードにコピーされました!
該当する場合は、アプリケーションレベルの制約により、以下の表の Hibernate Metadata Impact 列で説明されているデータベースレベルの制約が作成されます。
Java 固有のバリデーション制約
以下の表には、javax.validation.constraints パッケージに含まれる Java 仕様で定義されたバリデーション制約が示されています。
| アノテーション | プロパティータイプ | ランタイムチェック | Hibernate Metadata の影響 |
|---|---|---|---|
|
@AssertFalse |
ブール値 |
メソッドが false と評価することを確認します (アノテーションでなくコードで制約が表現されている場合に便利です)。 |
なし |
|
@AssertTrue |
ブール値 |
メソッドが true と評価することを確認します (アノテーションでなくコードで制約が表現されている場合に便利です)。 |
なし |
|
@Digits(integerDigits=1) |
数値または数値の文字列表現 |
プロパティーが |
カラムの精度とスケールを定義します。 |
|
@Future |
日付またはカレンダー |
未来の日付であるかを確認します。 |
なし |
|
@Max(value=) |
数値または数値の文字列表現 |
値が最大値以下であるかを確認します。 |
カラムに check 制約を追加します。 |
|
@Min(value=) |
数値または数値の文字列表現 |
値が最小値以上であるかを確認します。 |
カラムに check 制約を追加します。 |
|
@NotNull |
値が null でないかを確認します。 |
カラムが null でないかを確認します。 | |
|
@Past |
日付またはカレンダー |
過去の日付であるかを確認します。 |
カラムに check 制約を追加します。 |
|
@Pattern(regexp="regexp", flag=) or @Patterns( {@Pattern(…)} ) |
文字列 |
プロパティーが一致フラグが指定された正規表現に一致するかどうかを確認します。 |
なし |
|
@Size(min=, max=) |
アレイ、コレクション、マップ |
要素サイズが最小値以上で最大値以下であるかどうかを確認します。 |
なし |
|
@Valid |
オブジェクト |
紐付けされたオブジェクトに再帰的にバリデーションを実行します。オブジェクトがコレクションかアレイの場合は、要素は再帰的に検証されます。また、オブジェクトがマップの場合、値要素が再帰的に検証されます。 |
なし |
パラメーター @Valid は、javax.validation.constraints パッケージに存在しますが Bean Validation 仕様の一部です。
Hibernate Validator 固有のバリデーション制約
以下の表には、org.hibernate.validator.constraints パッケージに含まれるベンダー固有のバリデーション制約が含まれます。
| アノテーション | プロパティータイプ | ランタイムチェック | Hibernate Metadata の影響 |
|---|---|---|---|
|
@Length(min=, max=) |
文字列 |
文字列の長さが指定の範囲と一致するかを確認します。 |
カラムの長さを最大に設定します。 |
|
@CreditCardNumber |
文字列 |
文字列が正規の形式のクレジットカード番号であるかどうかを確認します (Luhn アルゴリズムの派生)。 |
なし |
|
@EAN |
文字列 |
文字列が正しくフォーマットされた EAN あるいは UPC-A コードであるかを確認します。 |
なし |
|
|
文字列 |
文字列がメールアドレスの仕様に準拠するかどうかを確認します。 |
なし |
|
@NotEmpty |
文字列が null あるいは空でないかを確認します。接続が null あるいは空でないかを確認します。 |
カラムは文字列の null ではありません。 | |
|
@Range(min=, max=) |
数値または数値の文字列表現 |
値が最小値以上で最大値以下であるかどうかを確認します。 |
カラムに check 制約を追加します。 |
13.2.3. カスタム制約を使用した Bean Validation リンクのコピーリンクがクリップボードにコピーされました!
Bean Validation API は、@NotNull や @Size などの標準の制約アノテーションのセットを定義します。しかし、これらの事前定義された制約が十分でない場合、バリデーションの要件に合ったカスタム制約を簡単に作成できます。
Bean Validation を作成する場合、カスタム制約には 制約アノテーションの作成 と 制約バリデーターの実装が必要になります。以下のコードサンプルは、JBoss EAP に同梱される bean-validation-custom-constraint クイックスタートから抜粋したものです。完全な作業例はこのクイックスタートを参照してください。
13.2.3.1. 制約アノテーションの作成 リンクのコピーリンクがクリップボードにコピーされました!
以下は、AddressValidator クラスで定義されたカスタム制約のセットを使用して、エンティティー Person の personAddress フィールドがバリデーションされる例を表しています。
エンティティー
Personを作成します。例:
Personクラスpackage org.jboss.as.quickstarts.bean_validation_custom_constraint; @Entity @Table(name = "person") public class Person implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue @Column(name = "person_id") private Long personId; @NotNull @Size(min = 4) private String firstName; @NotNull @Size(min = 4) private String lastName; // Custom Constraint @Address for bean validation @NotNull @Address @OneToOne(mappedBy = "person", cascade = CascadeType.ALL) private PersonAddress personAddress; public Person() { } public Person(String firstName, String lastName, PersonAddress address) { this.firstName = firstName; this.lastName = lastName; this.personAddress = address; } /* getters and setters omitted for brevity*/ }制約バリデーターファイルを作成します。
例:
Addressインターフェースpackage org.jboss.as.quickstarts.bean_validation_custom_constraint; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import javax.validation.Constraint; import javax.validation.Payload; // Linking the AddressValidator class with @Address annotation. @Constraint(validatedBy = { AddressValidator.class }) // This constraint annotation can be used only on fields and method parameters. @Target({ ElementType.FIELD, ElementType.PARAMETER }) @Retention(value = RetentionPolicy.RUNTIME) @Documented public @interface Address { // The message to return when the instance of MyAddress fails the validation. String message() default "Address Fields must not be null/empty and obey character limit constraints"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }例:
PersonAddressクラスpackage org.jboss.as.quickstarts.bean_validation_custom_constraint; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToOne; import javax.persistence.PrimaryKeyJoinColumn; import javax.persistence.Table; @Entity @Table(name = "person_address") public class PersonAddress implements Serializable { private static final long serialVersionUID = 1L; @Id @Column(name = "person_id", unique = true, nullable = false) @GeneratedValue(strategy = GenerationType.SEQUENCE) private Long personId; private String streetAddress; private String locality; private String city; private String state; private String country; private String pinCode; @OneToOne @PrimaryKeyJoinColumn private Person person; public PersonAddress() { } public PersonAddress(String streetAddress, String locality, String city, String state, String country, String pinCode) { this.streetAddress = streetAddress; this.locality = locality; this.city = city; this.state = state; this.country = country; this.pinCode = pinCode; } /* getters and setters omitted for brevity*/ }
13.2.3.2. 制約バリデーターの実装 リンクのコピーリンクがクリップボードにコピーされました!
アノテーションを定義したら、@Address アノテーションが付けられた要素のバリデーションが可能な制約バリデーターを作成する必要があります。これには、以下のように ConstraintValidator インターフェースを実装します。
例: AddressValidator クラス
package org.jboss.as.quickstarts.bean_validation_custom_constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.jboss.as.quickstarts.bean_validation_custom_constraint.PersonAddress;
public class AddressValidator implements ConstraintValidator<Address, PersonAddress> {
public void initialize(Address constraintAnnotation) {
}
/**
* 1. A null address is handled by the @NotNull constraint on the @Address.
* 2. The address should have all the data values specified.
* 3. Pin code in the address should be of at least 6 characters.
* 4. The country in the address should be of at least 4 characters.
*/
public boolean isValid(PersonAddress value, ConstraintValidatorContext context) {
if (value == null) {
return true;
}
if (value.getCity() == null || value.getCountry() == null || value.getLocality() == null
|| value.getPinCode() == null || value.getState() == null || value.getStreetAddress() == null) {
return false;
}
if (value.getCity().isEmpty()
|| value.getCountry().isEmpty() || value.getLocality().isEmpty()
|| value.getPinCode().isEmpty() || value.getState().isEmpty() || value.getStreetAddress().isEmpty()) {
return false;
}
if (value.getPinCode().length() < 6) {
return false;
}
if (value.getCountry().length() < 4) {
return false;
}
return true;
}
}
13.3. バリデーション設定 リンクのコピーリンクがクリップボードにコピーされました!
Bean Validation は、/META-INF ディレクトリーにある validation.xml ファイル内の XML を使用して設定できます。このファイルがクラスパスに存在する場合は、ValidatorFactory が作成されたときに設定が適用されます。
例: バリデーション設定ファイル
以下の例は、validation.xml ファイルの複数の設定オプションを示しています。これらすべての設定はオプションです。これらのオプションは、javax.validation パッケージを使用して設定することもできます。
<validation-config xmlns="http://jboss.org/xml/ns/javax/validation/configuration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/configuration">
<default-provider>
org.hibernate.validator.HibernateValidator
</default-provider>
<message-interpolator>
org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator
</message-interpolator>
<constraint-validator-factory>
org.hibernate.validator.engine.ConstraintValidatorFactoryImpl
</constraint-validator-factory>
<constraint-mapping>
/constraints-example.xml
</constraint-mapping>
<property name="prop1">value1</property>
<property name="prop2">value2</property>
</validation-config>
ノード default-provider では、Bean Validation プロバイダーを選択できます。これは、クラスパスに複数のプロバイダーがある場合に役に立ちます。message-interpolator プロパティーと constraint-validator-factory プロパティーは、javax.validation パッケージで定義されたインターフェース MessageInterpolator および ConstraintValidatorFactory の使用済み実装をカスタマイズするために使用されます。constraint-mapping 要素は、実際の制約設定が含まれる追加の XML ファイルをリストします。