Hibernate Validator リファレンスガイド

JBoss Enterprise Application Platform 5

JBoss Enterprise Application Platform 5 用

エディッション 5.1.2

Red Hat ドキュメンテーショングループ

概要

JBoss Enterprise Application Platform とそのパッチリリース用 Hibernate Validator リファレンスガイド。

第1章 制約の定義

1.1. 制約とは

制約は、該当する要素 (フィールド、プロパティ、または Bean) が準拠する必要があるルールです。このルールのセマンティックはアノテーションで表されます。通常、制約は制約制限をパラメータ化するために使用されるいくつかの属性を持ちます。この制約はアノテートされた要素に適用されます。

1.2. 組み込みの制約

Hibernate Validator には、ほとんどの基本的なデータチェックを行ういくつかの組み込み制約が含まれます。後で説明するように、これらの制約に制限されず、独自の制約をすぐに記述することができます。

表1.1 組み込みの制約

アノテーション 適用対象 実行時チェック Hibernate メタデータの影響
@Length(min=, max=) プロパティ (文字列) 文字列長が範囲に一致するかどうかをチェックします。 列長が最大値に設定されます。
@Max(value=) プロパティ (数値または数値の文字列表現) 値が最大値以下であるかどうかをチェックします。 列にチェック制約を追加します。
@Min(value=) プロパティ (数値または数値の文字列表現) 値が最小値以上であるかどうかをチェックします。 列にチェック制約を追加します。
@NotNull プロパティ 値が null であるかどうかをチェックします。 列が null ではありません。
@NotEmpty プロパティ 文字列が null または空白でないかどうかをチェックします。接続が null または空白でないかどうかをチェックします。 列が null ではありません (文字列に対して)。
@Past プロパティ (日付またはカレンダ) 日付が過去でないかどうかをチェックします。 列にチェック制約を追加します。
@Future プロパティ (日付またはカレンダ) 日付が未来であるかどうかをチェックします。 なし
@Pattern(regex="regexp", flag=) または @Patterns( {@Pattern(...)} ) プロパティ (文字列) プロパティが一致フラグが与えられた正規表現に一致するかどうかをチェックします (java.util.regex.Pattern を参照)。 なし
@Range(min=, max=) プロパティ (数値または数値の文字列表現) 値が最小値と最大値の間にあるかどうかをチェックします (最小値と最大値を含む)。 列にチェック制約を追加します。
@Size(min=, max=) プロパティ (アレイ、コレクション、マップ) 要素サイズが最小値と最大値の間にあるかどうかをチェックします (最小値と最大値を含む)。 なし
@AssertFalse プロパティ メソッドが false と評価することをチェックします (アノテーションではなくコードで表された制約の場合に役に立ちます)。 なし
@AssertTrue プロパティ メソッドが true と評価することをチェックします (アノテーションではなくコードで表された制約の場合に役に立ちます)。 なし
@Valid プロパティ (オブジェクト) 関連するオブジェクトに対して再帰的に検証を実行します。オブジェクトが Collection またはアレイの場合は、要素が再帰的に検証されます。オブジェクトが Map の場合は、値要素が再帰的に検証されます。 なし
@Email プロパティ (文字列) 文字列が電子メールアドレスの仕様に準拠するかどうかをチェックします。 なし
@CreditCardNumber プロパティ (文字列) 文字列が正規な形式のクレジットカード番号であるかどうかをチェックします (Luhn アルゴリズムの派生)。 なし
@Digits(integerDigits=1) プロパティ (数値または数値の文字列表現) プロパティが最大 integerDigits 整数桁と fractionalDigits 少数桁を持つ数であるかどうかをチェックします。 列の精度とスケールを定義します。
@EAN プロパティ (文字列) 文字列が適切な形式の EAN または UPC-A コードであるかどうかをチェックします。 なし

1.3. エラーメッセージ

Hibernate Validator では、デフォルトで一連のエラーメッセージが約 10 か国語に翻訳されています (希望する言語が含まれていない場合は、パッチを送ってください)。ValidatorMessages.properties または (ValidatorMessages_loc.properties) を作成してこれらのメッセージを上書きしたり、必要なキーを上書きしたりできます。独自の検証ツールのアノテーションを記述しつつ、独自の追加メッセージセットを追加することもできます。Hibernate Validator が resourceBundle または ValidatorMessage からキーを解決できない場合は、デフォルトの組み込みの値が使用されます。
または、Bean の検証ルールをプログラムでチェックすることにより ResourceBundle を提供できます。まったく異なる補間メカニズムが必要な場合は、org.hibernate.validator.MessageInterpolator の実装を提供できます (詳細については、JavaDoc を参照)。

1.4. 独自の制約の記述

組み込み制約セットを拡張するのは非常に門田んです。どの制約も、制約記述子 (アノテーション) と制約検証機能 (実装クラス) の 2 つの部分から構成されます。単純なユーザー定義の記述子を以下に示します。
@ValidatorClass(CapitalizedValidator.class)
@Target(METHOD)
@Retention(RUNTIME)
@Documented
public @interface Capitalized {
    CapitalizeType type() default Capitalize.FIRST;
    String message() default "has incorrect capitalization"
}
type はプロパティをどのように大文字にするかを示すパラメータです。これは、アノテーションビジネスに完全に依存するユーザーパラメータです。
message は、制約違反を定義するために使用するデフォルトの文字列であり、必須です。文字列をハードコーディングしたり、Java ResourceBundle メカニズムを使用して文字列の一部または全部を外部化したりできます。パラメータ値は、{parameter} 文字列が検出されたときにメッセージ内部に挿入されます (ここでの例では、Capitalization is not {type} により Capitalization is not FIRST が生成されます)。ValidatorMessages.properties の文字列全体を外部化することは推奨される方法です。「エラーメッセージ」 を参照してください。
@ValidatorClass(CapitalizedValidator.class)
@Target(METHOD)
@Retention(RUNTIME)
@Documented
public @interface Capitalized {
    CapitalizeType type() default Capitalize.FIRST;
    String message() default "{validator.capitalized}";
}


#in ValidatorMessages.properties
validator.capitalized = Capitalization is not {type}
示されたように、{} 表記は再帰的です。
記述子を検証実装にリンクするには、@ValidatorClass メタアノテーションを使用します。検証クラスパラメータは Validator<ConstraintAnnotation> を実装するクラスを指定する必要があります。
次に、検証機能を実装する必要があります (つまり、ルールチェック実装)。検証実装はプロパティの値をチェックでき (PropertyConstraint を実装することにより)、hibernate マッピングメタデータを変更してデータベースレベルで制約を表記できます (PersistentClassConstraint を実装することにより)。
public class CapitalizedValidator
        implements Validator<Capitalized>, PropertyConstraint {
    private CapitalizeType type;

    //part of the Validator<Annotation> contract,
    //allows to get and use the annotation values
    public void initialize(Capitalized parameters) {
        type = parameters.type();
    }

    //part of the property constraint contract
    public boolean isValid(Object value) {
        if (value==null) return true;
        if ( !(value instanceof String) ) return false;
        String string = (String) value;
        if (type == CapitalizeType.ALL) {
            return string.equals( string.toUpperCase() );
        }
        else {
            String first = string.substring(0,1);
            return first.equals( first.toUpperCase();
        }
    }
}
isValid() メソッドは、制約に違反した場合に false を返す必要があります。他の例については、組み込み検証機能実装を参照してください。
プロパティレベルの違反について説明しましたが、Bean レベルの検証アノテーションを記述できます。プロパティの戻りインスタンスを受け取る代わりに、Bean 自体が検証機能に渡されます。検証チェックを有効にするには、Bean 自体をアノテートします。ユニットテストスイートに小さなサンプルが存在します。
同じプロパティまたはタイプで制約を複数回適用できる場合は (異なるパラメータを使用)、以下のアノテーション形式を使用できます。
@Target(METHOD)
@Retention(RUNTIME)
@Documented
public @interface Patterns {
    Pattern[] value();
}

@Target(METHOD)
@Retention(RUNTIME)
@Documented
@ValidatorClass(PatternValidator.class)
public @interface Pattern {
    String regexp();
}
基本的に、アノテーションには、値属性が検証機能アノテーションのアレイとして含まれます。

1.5. ドメインモデルのアノテート

これまでにアノテーションについて説明したので、次は構文について説明します。
public class Address {
    private String line1;
    private String line2;
    private String zip;
    private String state;
    private String country;
    private long id;

    // a not null string of 20 characters maximum
    @Length(max=20)
    @NotNull
    public String getCountry() {
        return country;
    }

    // a non null string
    @NotNull
    public String getLine1() {
        return line1;
    }

    //no constraint
    public String getLine2() {
        return line2;
    }

    // a not null string of 3 characters maximum
    @Length(max=3) @NotNull
    public String getState() {
        return state;
    }

    // a not null numeric string of 5 characters maximum
    // if the string is longer, the message will
    //be searched in the resource bundle at key 'long'
    @Length(max=5, message="{long}")
    @Pattern(regex="[0-9]+")
    @NotNull
    public String getZip() {
        return zip;
    }

    // should always be true
    @AssertTrue
    public boolean isValid() {
        return true;
    }

    // a numeric between 1 and 2000
    @Id @Min(1)
    @Range(max=2000)
    public long getId() {
        return id;
    }
}
例はパブリックプロパティ検証のみを示していますが、任意の種類の可視性のフィールドをアノテートすることもできます。
@MyBeanConstraint(max=45)
public class Dog {
    @AssertTrue private boolean isMale;
    @NotNull protected String getName() { ... };
    ...
}
また、インターフェースをアノテートすることもできます。Hibernate Validator は、適切な検証機能アノテーションを読み取るために該当する Bean により拡張または実装されたすべてのスーパークラスとインターフェースをチェックします。
public interface Named {
    @NotNull String getName();
    ...
}

public class Dog implements Named {

    @AssertTrue private boolean isMale;

    public String getName() { ... };

}
Dog Bean が検証される場合は、名前プロパティが null であるかどうかがチェックされます。

第2章 Validator フレームワークの使用

Hibernate Validator は、制約が単一の場所で表記され (アノテートされたドメインモデル)、アプリケーションのさまざまなレイヤでチェックされるマルチレイヤデータ検証を実装するために使用することを目的としています。
この章では、さまざまなレイヤでの Hibernate Validator の使用について説明します。

2.1. データベーススキーマレベル検証

デフォルトで、Hibernate Annotations はエンティティに対して定義した制約をマッピングメタデータに変換します。たとえば、エンティティのプロパティがアノテートされた @NotNull である場合、その列は Hibernate により生成された DDL スキーマで not null として宣言されます。
hbm2ddl を使用することにより、ドメインモデル制約はデータベーススキーマに表されます。
何らかの理由でこの機能を無効にする必要がある場合は、hibernate.validator.apply_to_ddlfalse に設定します。

2.2. ORM 統合

Hibernate Validator は Hibernate とすべての純粋な Java Persistence プロバイダの両方を統合します。

2.2.1. Hibernate イベントベースの検証

Hibernate Validator は 2 つの組み込み Hibernate イベントリスナを持ちます。PreInsertEvent または PreUpdateEvent が発生した場合、常にこれらのリスナがエンティティインスタンスのすべての制約を検証し、制約に違反した場合に例外をスローします。基本的に、オブジェクトは、Hibernate により挿入や更新が行われる前にチェックされます。これには、カスケードで適用される変更も含まれます。これは、検証プロセスを有効にする最も便利で簡単な方法です。制約違反時に、イベントが、各エラーを定義する InvalidValue のアレイを含むランタイム InvalidStateException を発生させます。
Hibernate Validator がクラスパスに存在する場合、Hibernate Annotations (または Hibernate EntityManager) は透過的にこれを使用します。何らかの理由でこの統合を無効にする場合は、hibernate.validator.autoregister_listeners を false を設定します。

注記

Bean が検証アノテーションでアノテートされない場合は、実行時のパフォーマンスが影響されません。
手動で Hibernate Core のイベントリスナを設定する必要がある場合は、hibernate.cfg.xml の以下の設定を使用します。
<hibernate-configuration>
    ...
    <event type="pre-update">
        <listener 
          class="org.hibernate.validator.event.ValidateEventListener"/>
    </event>
    <event type="pre-insert">
        <listener 
          class="org.hibernate.validator.event.ValidateEventListener"/>
    </event>
</hibernate-configuration>

2.2.2. Java Persistence イベントベースの検証

Hibernate Validator はイベントベースの検証のために Hibernate に限定されません。Java Persistence エンティティリスナが利用可能です。リッスンされたエンティティが保持または更新された場合、常に Hibernate Validator がエンティティインスタンスのすべての制約を検証し、制約が違反したときに例外をスローします。基本的に、オブジェクトは、Java Persistence プロバイダによる挿入または更新が行われる前にチェックされます。これには、カスケードにより適用される変更も含まれます。制約違反時に、イベントは、各エラーを定義する InvalidValue のアレイを含むランタイム InvalidStateException を発生させます。
クラスを検証可能にする方法は以下のとおりです。
@Entity
@EntityListeners( JPAValidateListener.class )
public class Submarine {
    ...
}

注記

Hibernate イベントと比較して、Java Persistence リスナには 2 つの欠点があります。各検証可能なエンティティに対してエンティティリスナを定義する必要があります。プロバイダにより生成された DDL は制約を反映しません。

2.3. アプリケーションレベルの検証

Hibernate Validator は、アプリケーションコードのどの場所でも適用できます。
ClassValidator personValidator = new ClassValidator( Person.class );
ClassValidator addressValidator = new ClassValidator( Address.class, ResourceBundle.getBundle("messages", Locale.ENGLISH) );

InvalidValue[] validationMessages = addressValidator.getInvalidValues(address);
最初の 2 行はクラスチェックのために Hibernate Validator を準備します。最初の行は Hibernate Validator に組み込まれたエラーメッセージに依存します (「エラーメッセージ」 を参照)。次の行はこれらのメッセージのリソースバンドルを使用します。これらの行は一度だけ実行し、検証機能インスタンスをキャッシュすることが推奨されます。
3 行目は実際に Address インスタンスを検証し、InvalidValue のアレイを返します。アプリケーションロジックはエラーに反応できるようになります。
また、Bean 全体の代わりに特定のプロパティをチェックすることもできます。これは、プロパティごとのユーザーの対話に役に立つことがあります。
ClassValidator addressValidator = new ClassValidator( Address.class, ResourceBundle.getBundle("messages", Locale.ENGLISH) );

//only get city property invalid values
InvalidValue[] validationMessages = addressValidator.getInvalidValues(address, "city");

//only get potential city property invalid values
InvalidValue[] validationMessages = addressValidator.getPotentialInvalidValues("city", "Paris");

2.4. プレゼンテーションレイヤの検証

JSF と JBoss Seam を使用する場合は、Seam の JSF タグ <s:validate><s:validateAll/> を使用してプレゼンテーションレイヤで検証プロセスをトリガし、制約をモデルで表記し、違反をビューに表示することができます。
<h:form>
    <div>
        <h:messages/>
    </div>
    <s:validateAll>
        <div>
            Country:
            <h:inputText value="#{location.country}" required="true"/>
        </div>
        <div>
            Zip code:
            <h:inputText value="#{location.zip}" required="true"/>
        </div>
        <div>
            <h:commandButton/>
        </div>
    </s:validateAll>
</h:form>
さらに、Ajax4JSF をループに追加することにより、再度検証定義の重複なしでクライアントサイド検証に複数の追加タグが提供されます。
詳細については、JBoss Seam ドキュメンテーションを参照してください。

2.5. 違反情報

検証情報キャリアとして、Hibernate は InvalidValue のアレイを提供します。各 InvalidValue は個々の問題を定義する複数のメソッドを持ちます。
getBeanClass() はエラーがある Bean タイプを取得します。
getBean() はエラーがあるインスタンスを取得します (getPotentianInvalidValues() を使用しない場合など)。
getValue() はエラーがある値を取得します。
getMessage() は適切な各国語に翻訳されたエラーメッセージを取得します。
getRootBean() は問題を生成するルート Bean インスタンスを取得し (@Valid と併用すると便利)、getPotentianInvalidValues() が使用されている場合は null になります。
getPropertyPath() はルート Bean からのエラーがあるプロパティのドット付きパスを取得します。

付録A 改訂履歴

改訂履歴
改訂 5.1.2-2.4002013-10-30Rüdiger Landmann
Rebuild with publican 4.0.0
改訂 5.1.2-22012-07-18Anthony Towns
Rebuild for Publican 3.0
改訂 5.1.2-100Thu Dec 8 2011Jared Morgan
JBoss Enterprise Application Platform 5.1.2 GA に対する変更を追加。本ガイド文書の変更に関する情報は、『リリースノート 5.1.2』を参照してください。
改訂 5.1.1-100Mon Jul 18 2011Jared Morgan
JBoss Enterprise Application Platform 5.1.1 GA に対する変更を追加。本ガイド文書の変更に関する情報は、『リリースノート 5.1.1』を参照してください。
改訂 5.1.0-100Wed Sep 15 2010Laura Bailey
新しいバージョン要件に応じてバージョン番号が変更されました。
JBoss Enterprise Application Platform 5.1.0.GA 向けに改訂されました。

法律上の通知

Copyright © 2011 Red Hat, Inc.
This document is licensed by Red Hat under the Creative Commons Attribution-ShareAlike 3.0 Unported License. If you distribute this document, or a modified version of it, you must provide attribution to Red Hat, Inc. and provide a link to the original. If the document is modified, all Red Hat trademarks must be removed.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, Red Hat Enterprise Linux, the Shadowman logo, JBoss, OpenShift, Fedora, the Infinity logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries.
Linux® is the registered trademark of Linus Torvalds in the United States and other countries.
Java® is a registered trademark of Oracle and/or its affiliates.
XFS® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States and/or other countries.
MySQL® is a registered trademark of MySQL AB in the United States, the European Union and other countries.
Node.js® is an official trademark of Joyent. Red Hat Software Collections is not formally related to or endorsed by the official Joyent Node.js open source or commercial project.
The OpenStack® Word Mark and OpenStack logo are either registered trademarks/service marks or trademarks/service marks of the OpenStack Foundation, in the United States and other countries and are used with the OpenStack Foundation's permission. We are not affiliated with, endorsed or sponsored by the OpenStack Foundation, or the OpenStack community.
All other trademarks are the property of their respective owners.