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)

数値または数値の文字列表現

プロパティーが integerDigits までの整数部と、fractionalDigits までの小数部を持つ数字であるかを確認します。

カラムの精度とスケールを定義します。

@Future

日付またはカレンダー

未来の日付であるかを確認します。

なし

@Max(value=)

数値または数値の文字列表現

値が最大値以下であるかを確認します。

カラムに check 制約を追加します。

@Min(value=)

数値または数値の文字列表現

値が最小値以上であるかを確認します。

カラムに check 制約を追加します。

@NotNull

 

値が null でないかを確認します。

カラムが null でないかを確認します。

@Past

日付またはカレンダー

過去の日付であるかを確認します。

カラムに check 制約を追加します。

@Pattern(regexp="regexp", flag=) or @Patterns( {@Pattern(…​)} )

String

プロパティーが一致フラグが指定された正規表現に一致するかどうかを確認します。java.util.regex.Pattern を参照してください。

なし

@Size(min=, max=)

アレイ、コレクション、マップ

要素サイズが最小値以上で最大値以下であるかどうかを確認します。

なし

@Valid

オブジェクト

紐付けされたオブジェクトに再帰的にバリデーションを実行します。オブジェクトがコレクションかアレイの場合は、要素は再帰的に検証されます。また、オブジェクトがマップの場合、値要素が再帰的に検証されます。

なし

注記

パラメーター @Valid は、javax.validation.constraints パッケージに存在しますが Bean Validation 仕様の一部です。

Hibernate Validator 固有のバリデーション制約

以下の表には、org.hibernate.validator.constraints パッケージに含まれるベンダー固有のバリデーション制約が含まれます。

アノテーションプロパティータイプランタイムチェックHibernate Metadata の影響

@Length(min=, max=)

String

文字列の長さが指定の範囲と一致するかを確認します。

カラムの長さを最大に設定します。

@CreditCardNumber

String

文字列が正規の形式のクレジットカード番号であるかどうかを確認します (Luhn アルゴリズムの派生)。

なし

@EAN

String

文字列が正しくフォーマットされた EAN あるいは UPC-A コードであるかを確認します。

なし

@Email

String

文字列がメールアドレスの仕様に準拠するかどうかを確認します。

なし

@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 クラスで定義されたカスタム制約のセットを使用して、エンティティー PersonpersonAddress フィールドがバリデーションされる例を表しています。

  1. エンティティー 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*/
    }

  2. 制約バリデーターファイルを作成します。

    例: 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;
    }
}