10 検証とビジネス・ルールの宣言的な定義
この章の内容は次のとおりです。
宣言的な検証について
ADFエンティティ・オブジェクトの概要エディタを使用して宣言的検証規則を定義します。このような規則は、エンティティ・オブジェクトのXMLファイルに格納されます。組込みの宣言的検証に加えて、カスタム規則を作成できます。
検証ルールを作成および管理する最も容易な方法は、宣言的検証ルールを使用することです。宣言的検証規則は概要エディタを使用して定義され、一旦作成されると、エンティティ・オブジェクトのXMLファイルに保存されます。宣言的検証は、エンティティ・オブジェクトのJavaファイルに保存されているプログラムによる検証(「プログラムによる検証とビジネス・ルールの実装」)とは異なります。
Oracle ADFでは、大部分のビジネス上のニーズを満たすことができる組込みの宣言的な検証ルールが用意されています。再利用するカスタム検証規則がある場合は、コーディングを行ってIDEに追加し、JDeveloperから直接規則を利用できます。カスタム検証ルールは高度なトピックとなり、「カスタム検証規則の実装」で説明されています。「ビジネス・ルールとトリガーでのGroovy式の使用」で説明されているように、Groovy式を検証の基礎にすることもできます。
検証ルールを追加する際、適切なエラー・メッセージを提供し、後に必要に応じて容易に他の言語に翻訳できます。検証のトリガー方法を定義し、重大度レベルを設定することもできます。
宣言的な検証のユースケースと例
ADFビジネス・コンポーネントを含むFusion Webアプリケーションでは、検証コードの大半がエンティティ・オブジェクト内で定義されます。ビジネス・ロジックをこのように再利用可能な共有コンポーネントにカプセル化することにより、ビジネス情報にアクセスするすべてのビュー・オブジェクトやクライアントで情報が一貫して検証され、検証の保管先を集中化することによって管理が容易になります。
宣言的検証を使用する場合のもう1つの利点は、独自に検証を作成する場合とは異なり、検証のフレームワークによってバッチ検証の複雑な例外処理が自動的に行われることです。これにより、アプリケーション固有の検証規則ロジックに専念できます。
モデル・レイヤーでは、ADFモデル検証規則をコレクションの属性に設定できます。エンティティ・オブジェクトで利用できる宣言的検証機能の多くはモデル・レイヤーでも利用でき、アプリケーションはビジネス・レイヤー検証に加えてモデル・レイヤー検証の使用も保証する必要があります。詳細は、「ADFモデル・レイヤーでの検証の使用」を参照してください。
ADFビジネス・コンポーネント・アプリケーション・モジュールのデータ・コントロールを使用する場合、モデル・レイヤー検証を使用する必要はありません。可能であれば、すべての検証規則を、ビジネス・レイヤー内の再使用と管理が容易で一元管理されたエンティティ・オブジェクトに定義することを検討してください。その他のデータ・コントロール・タイプでは、ADFモデル・レイヤー検証のほうが便利です。
宣言的な検証の追加機能
宣言的な検証を使用する前に、他のOracle ADF機能を理解しておくと役立つ場合があります。必要に応じて、宣言的動作を超えて、より複雑な検証規則をビジネス・ドメイン・レイヤーに実装することができます。次に、関連する他の機能へのリンクを示します。
-
「メソッド・バリデータの使用」では、メソッド・バリデータを使用したカスタム検証コードの起動方法を説明しています。
-
「カスタム検証規則の実装」では、基本的な宣言的ルール・セットを独自のカスタム・ルールで拡張する方法を詳しく説明しています。
検証を実装する場所の決定
Oracle ADFは、各レイヤーで検証を実装できるModel-View-Controller (MVC)アーキテクチャ・デザイン・パターンに準拠しています。ビジネス・ニーズに応じて、特定のレイヤーで検証を実装します。
「Oracle ADFアーキテクチャ」で説明したように、Fusion WebアプリケーションのModel-View-Controller (MVC)アーキテクチャには、ビジネス・ロジック、ページ・ナビゲーション、ユーザー・インタフェースの明確な分離を提供する複数のレイヤーがあります。これらのレイヤーは、検証の実装に複数のオプションを提供し、各レイヤーでの検証の使用には利点と欠点があります。検証を実装するために選択する場所は、特定のビジネス・ニーズまたはユースケースによって決まります。一般に、検証を行う場所がデータ・ソースに近いほど、集中化されるため保守が簡単になり、ユーザー・インタフェースに近いほど、実行時にフィードバックがより即時に提供されます。
データ・サービス・レイヤー: データベースであるか、Webサービスであるか、その他のデータ・ソースであるかにかかわらず、データ・サービス・レイヤーは、一般にアプリケーション自体のコンテキストの外部に存在し、各データ・フィールドの性質を定義する制約を採用します。データ・サービス制約は、通常は格納されるデータのすべての部分に対して定義され、そのデータの完全性を維持するために非常に重要です。ただし、データがデータ・ソースに到達する(通常はアプリケーションがトランザクションをコミットしようとしたとき)までは施行されないため、これらの制約のみに依存することは効果的でも効率的でもありません。これには、クライアントUIからデータ・ソースへのラウンド・トリップが必要であり、単一レコードでの単一のエラーがトランザクション全体のロールバックの原因となることがあります。
ビジネス・サービス・レイヤー: ADFビジネス・コンポーネント(エンティティ・オブジェクトやビュー・オブジェクトなど)のビジネス・サービス・レイヤーで実装するビジネス・ルールは、データ・ソースとのラウンド・トリップを必要としないため、データ・サービス制約よりも効率的です。また、特定のエンティティ・オブジェクトの属性に対して定義されたビジネス・ルールは、そのエンティティ・オブジェクトを使用するすべてのページに適用されるため、これらはビュー・レイヤーに実装されたバリデータよりも保守が簡単です。属性レベルのバリデータに加えて、ある属性の値の有効性が別の属性の値に依存する場合は、エンティティ・レベルのバリデータを実装することもできます。たとえば、DateShipped
はDateOrdered
よりも大きい必要があります。この章では、この種類のビジネス・ルールについて説明します。
モデル・レイヤー: 他の種類のビジネス・ルールほど一般的には使用されませんが、モデル・レイヤー検証も役立つ場合があります。ビジネス・サービスへのバインドに対してビジネス・ルールを定義できます。この機能は、たとえばアプリケーションが外部Webサービスを使用するため、ビジネス・サービスに検証を実装できない場合に役立つことがあります。「ADFモデル・レイヤーでの検証の使用」を参照してください。
ビュー・レイヤー: ユーザーの観点から、ビュー・レイヤー検証が最も効率的です。これらは、ユーザーがデータを入力してから特定のフィールドを離れた(タブ移動した)場合に即時のフィードバックを提供します。アプリケーション・サーバーとの通信は必要としません。ただし、ビュー・レイヤー・バリデータはページに実装されるため、特定のデータ・フィールドへのアクセスを提供するすべてのページで、そのフィールドに対する検証を定義する必要があります。『Oracle ADF FacesによるWebユーザー・インタフェースの開発』の「入力の検証および変換」を参照してください。
検証サイクルの理解
永続エンティティ行属性の変更時またはエンティティ行の作成時に、ADFエンティティ行に対して検証を強制できます。
それぞれのエンティティ行は、データが有効であるかどうかを追跡します。既存のエンティティ行をデータベースから取得すると、エンティティは有効であると判断されます。既存のエンティティ行の最初の持続属性が変更された場合、または、新しいエンティティ行が作成された場合、エンティティは無効であるとマークされます。
エンティティが無効な状態にある場合、エンティティを有効にする前に、構成した宣言的な検証と、実装したプログラム的な検証規則が再度評価されます。あるエンティティ行が実行時に有効であるかどうかは、その行でisValid()
メソッドをコールして確認できます。
ノート:
属性は(デフォルトで)空欄のままにできるため、属性に値が含まれていない場合、検証はトリガーされません。たとえば、ユーザーが新しいエンティティ行を作成して特定の属性の値を入力しなかった場合、その属性に関する検証は実行されません。この状況で検証を強制的に実行するには、属性に必須フラグを設定します。
エンティティ・オブジェクト検証規則のタイプ
エンティティ・オブジェクト検証規則は、属性レベルおよびエンティティレベルのいずれかの基本カテゴリに分類できます。
属性レベルの検証規則
特定のエンティティ・オブジェクト属性に対する属性レベルの検証規則は、エンド・ユーザーまたはプログラム・コードによる属性値の変更が試行されるとトリガーされます。属性を設定する順序は指定できないため、属性レベルの検証規則は、規則の成否がその属性の候補値のみに依存する場合にのみ使用する必要があります。
属性レベルの検証を次に示します。
-
注文の
OrderDate
の値には、過去の日付は設定できません。 -
製品の
ProductId
属性は、既存の製品である必要があります。
エンティティ・レベルの検証規則
その他のすべての検証規則は、エンティティ・レベルの検証規則となります。これらの規則には、実装の際、規則の成否の決定に2つ以上のエンティティ属性、または、構成される子エンティティ行を考慮する必要があります。
エンティティ・レベルの検証を次に示します。
-
OrderShippedDate
の値は、OrderDate
より後の日付を設定します。 -
注文の
ProductId
属性は、既存の製品である必要があります。
エンティティ・レベルの検証規則は、Row
に対しvalidate()
メソッドをコールするとトリガーされます。次の場合にトリガーされます。
-
エンティティ・オブジェクトにおいてメソッドを明示的にコールした場合
-
無効なエンティティ行を含むビュー行においてメソッドを明示的にコールした場合
-
ビュー・オブジェクトのイテレータにより、現在の行の変更を許可する前に、ビュー・オブジェクトの現在の行に対してメソッドがコールされた場合
-
トランザクションのコミット時、データベースへ変更を送信する前に、保留中の変更リスト内の無効なエンティティが処理によって有効にされた場合
トランザクションのコミット処理の一環として、エンティティ・レベルの検証規則は複数回起動できます(指定された限度回数まで)。詳細は、「無限検証サイクルの回避」を参照してください。
コミット処理と検証の理解
トランザクションのコミット処理は、3つの基本的なフェーズに分かれています。
-
保留中の変更リスト内のすべての無効エンティティ行が有効であることを確認します。
-
適切なDML操作を実行し、保留中の変更をデータベースに送信します。
-
トランザクションをコミットします。
エンティティ・オブジェクト内に、SELECT
文内の送信済の変更の参照に応じて問合せまたはストアド・プロシージャを実行するようなビジネス検証ロジックがある場合、「ビュー・アクセッサによる行セットのアクセスに関する必知事項」に示すbeforeCommit()
メソッドを使用してコーディングする必要があります。このメソッドは、すべてのDML文が適用された後に実行されるため、そのメソッドが実行した問合せやストアド・プロシージャでは、保存された、コミット前の保留中の変更をすべて参照できます。
注意:
同一のHTTPリクエスト内でトランザクションのコミットまたはロールバックが必ず実行される場合を除き、Webアプリケーションでトランザクション・レベルのpostChanges()
メソッドを使用しないでください。このメソッドは、検証前の変更をコミットせず、トランザクションから強制的に送信します。使用した場合、複数の異なるクライアントにより、アプリケーション・モジュールとデータベース接続の両方がプールされ、シリアルに共有されるという事態が環境内で発生する可能性があります。
検証順序に対するコンポジットの影響の理解
構成される側の子エンティティ行は、それを構成する親エンティティ・オブジェクトに不可欠であるとみなされるため、構成される側の子エンティティ行になんらかの変更を加えると、親エンティティは無効であるとマークされます。たとえば、注文の明細項目を変更する場合、注文全体が変更されるか無効であるとみなされます。
したがって、コンポジット・エンティティを検証する場合、現在無効な構成される側の子エンティティが最初に検証されます。この動作は再帰的で、無効な構成される側の子が存在する場合、さらに深くドリルします。
無限検証サイクルの回避
現在のエンティティや他のエンティティの属性を更新するコードが検証規則に含まれている場合、エンティティの検証により、対象のエンティティやその他のエンティティが無効になる場合があります。保留中の変更リスト内のすべての無効なエンティティを検証するトランザクションのコミット処理フェーズの一環として、このトランザクションは、保留中のすべてのエンティティ行が有効になるまで、1回につき保留中の変更リストを複数回(指定された限度回数まで)パスします。
検証のパスの最大回数は、トランザクション・レベルの検証しきい値設定によって指定します。この設定のデフォルト値は10です。後続のパスで自身を検証するための適切なロジックが関連のエンティティに含まれている場合は、しきい値の回数を増やすことができます。
10回パスした後に、リスト内に無効なエンティティが残っている場合、次の例外が発生します。
JBO-28200: Validation threshold limit reached. Invalid Entities still in cache
これは、意図しないエンティティの無効化を繰り返すような処理を回避するため、検証規則コードをデバッグする必要があることを示しています。
検証しきい値を変更するには:
- 「アプリケーション」ウィンドウで、目的のアプリケーション・モジュールをダブルクリックします。
- 概要エディタで、「構成」ナビゲーション・タブをクリックし、検証しきい値を調整する構成のハイパーリンクを選択します。
- アプリケーション・モジュール構成(
bc4j.xcfg
ファイル)の概要エディタで、「プロパティ」タブをクリックし、「プロパティの追加」をクリックします。 - 「プロパティの追加」ダイアログで、
jbo.validation.threshold
プロパティを選択し、「OK」をクリックします。 - 概要エディタの「プロパティ」リストに、
jbo.validation.threshold
プロパティの新しい値を入力し、変更を保存します。
検証しきい値は、次に示すようにSetValidationThreshold()
メソッドを使用してプログラム的に変更することもできます。この例では新しいしきい値が12です。
oracle.jbo.server.DBTransaction::setValidationThreshold(12)
検証が失敗したときに行われる処理
エンティティ・オブジェクトの検証規則で例外がスローされた場合、その例外はバンドルされ、クライアントに戻されます。トランザクションのpostChanges
処理中、イベントを処理するためオーバーライドしたメソッドによって検証の失敗がスローされる場合、現在のpostChanges
サイクルですでに実行されている可能性のあるデータベースのINSERT
、UPDATE
およびDELETE
文がロールバックされます。
ノート:
例外のバンドルは、ADFモデル・ベースのWebアプリケーションのデフォルトの動作ですが、Oracle ADFモデル・テスターまたはSwingのバインディングではデフォルト動作ではありません。Oracle ADFモデル・テスターまたはSwingのクライアントでは、例外のバンドルに追加の構成が必要です。
エンティティ・オブジェクト行の状態の理解
エンティティ行がメモリー内にある場合、行の論理状態を反映したエンティティ状態になります。図10-1に、異なるエンティティ行の状態と、エンティティ行の状態の変化を示します。エンティティ行が最初に作成される場合、状態はNew
です。setNewRowState()
メソッドを使用すると、エンティティをInitialized
としてマーキングできます。これにより、エンティティはトランザクションの保留中の変更リストから除外され、ユーザーが1つ以上の属性を設定したときにNew
状態に戻ります。これによって、複数の初期化行を作成し、ユーザーが修正したものだけをポストできます。
Unmodified
状態とは、データベースから取得されてから、まだ変更されていないエンティティの状態を表します。また、New
またはModified
状態のエンティティがトランザクションのコミット完了後に遷移する状態でもあります。トランザクション内で削除のために保留中の場合は、Unmodified
エンティティ行はDeleted
状態へと遷移します。最終的に、New
状態の行がトランザクションのコミット前に削除されたり、Unmodified
状態の行が正常に削除された場合、その行はDead
状態へと遷移します。
getEntityState()
およびgetPostState()
メソッドを使用すると、ビジネス・ロジック・コードのエンティティ行の現在の状態にアクセスできます。getEntityState()
メソッドは、トランザクションに関するエンティティ行の現在の状態を返します。また、getPostState()
メソッドは、postChanges()
メソッドを使用してトランザクションをコミットせずに保留中の変更をポストした後の、データベースに関するエンティティ行の現在の状態を返します。
たとえば新しい行を開始すると、getEntityState()
とgetPostState()
の両方がSTATUS_NEW
を返します。その後、行をポストすると(コミットやロールバックの前)、その行のエンティティ状態はSTATUS_NEW
になり、ポスト状態はSTATUS_UNMODIFIED
になります。その後その行を削除しても、トランザクションにとってその行はまだ新規のため、エンティティ状態はSTATUS_NEW
のままになります。ただしポスト状態はSTATUS_DEAD
になります。
バンドル例外モードの理解
アプリケーション・モジュールにはバンドル例外モードと呼ばれる機能があり、Webアプリケーションは発生した最初のエラーのみでなく、失敗した検証例外の最大セットをエンド・ユーザーに簡単に提示できます。ADFビジネス・コンポーネント・アプリケーション・モジュール・プールでは、Webアプリケーションに対してバンドル例外モードをデフォルトで有効にしています。
このデフォルト設定は、通常変更する必要はありません。ただし、検証例外がスローされる方法に影響を与えることからデフォルトで有効になっていることを理解することが重要です。Java言語およびJavaランタイムは単一例外オブジェクトのスローのみをサポートするため、バンドルされた検証例外は、例外のセットを、それを含む新しい親例外の詳細としてラップすることで実装されます。たとえば、単一エンティティ・オブジェクトの複数の属性で属性レベルの検証ができない場合、これら複数のValidationException
オブジェクトは、RowValException
にラップされます。このラップ例外には、検証できなかった行の行キーが含まれています。トランザクションのコミット時に、コミット中に実行された検証を複数の行で渡せなかった場合、すべてのRowValException
オブジェクトは、包含するTxnValException
オブジェクトにラップされます。
カスタム・エラー処理コードを記述するときは、JboException
基本例外クラスのgetDetails()
メソッドを使用すると、内部にバンドルされている例外を再帰的に処理できます。
ノート:
ここに記載されている例外クラスはすべて、oracle.jbo
パッケージのクラスです。
エンティティ・オブジェクトおよび属性への検証規則の追加
ADFビジネス・コンポーネントを使用すると、検証規則をエンティティ・オブジェクトに宣言的に追加できます。
エンティティ・オブジェクトに検証規則を追加する手順は、ほとんどの検証規則と同じで、「検証ルールの追加」ダイアログを使用します。このダイアログは、「ビジネス・ルール」ページの「追加」アイコンをクリックして、概要エディタから開くことができます。
「検証ルールの追加」ダイアログを使用して規則を宣言的に定義すると、その規則定義が属性またはエンティティ・オブジェクトの有効な条件を指定することに注意する必要があります。実行時に、ユーザーが入力したエントリが規則定義に対して評価され、エントリが指定された基準を満たさない場合、エラーまたは警告が発せられます。たとえば、12より小さいか等しい
必要のある属性に対して長さのバリデータを指定した場合、エントリが12文字よりも長いと検証が失敗し、エラーまたは警告が発行されます。
エンティティまたは属性への検証規則の追加方法
エンティティ・オブジェクトに宣言的な検証規則を追加するには、概要エディタの「ビジネス・ルール」ページを使用します。
始める前に:
エンティティ・オブジェクトと属性での検証規則の使用方法に関する知識があると役立つ場合があります。詳細は、「エンティティ・オブジェクトおよび属性への検証規則の追加」を参照してください。
また、他の検証機能を使用して追加できる機能についても理解しておくと役立ちます。詳細は、「宣言的な検証の追加機能」を参照してください。
検証規則を追加するには:
エンティティ・オブジェクトまたは属性の検証規則の表示および編集方法
エンティティ・オブジェクトの概要エディタの「ビジネス・ルール」ページには、エンティティの検証規則とその属性がツリー・コントロールで表示されます。エンティティ全体に適用する検証規則を表示するには、「エンティティ」ノードを展開します。属性に適用する検証規則を表示するには、「属性」ノードを展開し、属性を展開します。
概要エディタの「ビジネス・ルール」ページに表示される検証規則には、定義した規則だけでなく、必須や精度などのデータベース制約も含まれます。検証規則を開いて編集するには、その規則をダブルクリックするか選択し、「編集」アイコンをクリックします。
検証規則の追加時の処理
エンティティ・オブジェクトに検証ルールを追加すると、エンティティ・オブジェクトのXMLドキュメントが更新され、使用したルールと入力したルール・プロパティを示すエントリが含まれます。たとえば、次の例に示すように、レンジ検証ルールをDiscountAmount
属性に追加すると、XMLファイルにRangeValidationBean
エントリが含まれます。
<Attribute Name="DiscountAmount" IsNotNull="true" ColumnName="DISCOUNT_AMOUNT" . . . <validation:RangeValidationBean xmlns="http://xmlns.oracle.com/adfm/validation" Name="DiscountAmount_Rule_0" ResId="DiscountAmount_RangeError_0" OnAttribute="DiscountAmount" OperandType="LITERAL" Inverse="false" MinValue="0" MaxValue="40"/> . . . </Attribute>
実行時に、この規則はこの宣言情報に基づいてエンティティ・オブジェクトによって適用されます。
エンティティおよび属性の検証規則に関する必知事項
宣言的検証は、規則を配置した場所に応じて、エンティティ・レベルおよび属性レベルの両方の検証に適用されます。エンティティ・レベルの検証規則は、ユーザーが保留中の変更をコミットしようとした場合または行を移動しようとした場合に適用されます。また、ユーザーが関連属性の値を変更する場合、属性レベルの検証規則が適用されます。
一意キー・バリデータ(「キー値の一意性を確認する方法」で説明している)はエンティティ・レベルでのみ使用できます。内部ではUnique Keyバリデータが属性レベルのバリデータとして機能します。したがって、ユーザーはバリデータが検証中のキーのキー属性をタブ・アウトすると、検証エラーが確認できます。エンティティの内部キャッシュには重複を含むことができず、属性値を設定するとこれに違反するため、この操作を行います。キャッシュの一貫性チェックは属性値の設定中に行われるため、このチェックは属性値を設定する際に行う必要があります。
ベスト・プラクティス:
1つの属性の有効性が1つ以上の他の属性に依存する場合は、属性の検証ではなくエンティティの検証を使用してこの規則を適用します。この処理を実行する例には次のようなものがあります。
-
ある属性を別のものと比較する比較バリデータがある場合
-
他の属性の値を調査して式のブランチ化を制御し、この他の属性の値に応じて様々な方法で属性を検証する式バリデータがある場合
-
条件付き実行を使用する場合、および事前条件式に検証しているもの以外の属性が含まれている場合
エンティティ・オブジェクト・バリデータは、エンティティのいずれかが変更された場合に必ずトリガーされます。パフォーマンスを改善するには、規則内でロールを担う属性を示し、この種の属性が1つ以上変更された場合にのみ、規則をトリガーさせます。属性のトリガーの詳細は、「検証実行のトリガー」を参照してください。
値リストおよび属性検証規則に関する必知事項
開発者は、ユーザー・インタフェースでの選択リストの表示をサポートするために、ビュー・オブジェクトに対して値リスト(LOV)属性を定義できます。ビュー・オブジェクトのLOV属性は、表示する値を提供するために、データ・ソース・ビュー・オブジェクトに依存します。LOV機能では問い合せるデータ・ソースには有効な値のみが含まれていることを前提としているため、ユーザー・インタフェースに選択リストが表示される前に、データ・ソース・ビュー・オブジェクト属性に対して定義されている検証規則は抑制されます。したがって、LOVを定義する開発者は、「ビュー・オブジェクト属性の値リスト(LOV)での作業」で説明しているように、データソース・ビュー・オブジェクトにより返される値リストには有効な値のみが含まれるようにする必要があります。
組込みの宣言的な検証規則の使用
ADFビジネス・コンポーネントには、多数の検証ユース・ケースを実現するために組込みの宣言的検証規則が数多く用意されています。
組込みの宣言的な検証規則は、大部分のビジネス上のニーズを満たすことができます。このような規則は、コードの記述がないため実装が簡単です。検証のタイプとその使用方法を選択するには、ユーザー・インタフェース・ツールを使用します。
組込みの宣言的な検証規則を使用すると、次のことが可能です。
-
キー値が一意であるかの確認(主キーまたはその他の一意キー)
-
キー値の存在の判別
-
属性とリテラル値からSQL問合せまでのすべての値の比較
-
リテラル・リスト、SQL問合せ、またはビュー属性の可能性がある値のリストに対する検証
-
値が一定の範囲内にあるか、または特定のバイト数または文字数に制限されるかの確認
-
正規表現による検証またはGroovy式の評価
-
アクセッサで使用可能な子エンティティで、集約によって定義された関係を値が満たしているかどうかの確認
-
Javaメソッドに定義した検証条件を使用した、エンティティでの検証
キー値の一意性を確認する方法
一意キー・バリデータは、エンティティ・オブジェクトの主キー値が常に一意であるかどうかを確認します。また、一意キー・バリデータは、その属性が代替キーとして定義されている場合、非主キー属性にも使用できます。代替キーの定義方法は、「代替キー値の定義方法」を参照してください。
キー属性値が変更されるたびに、この規則は、新しいキーがこのエンティティ・オブジェクト・クラスの他のエンティティ・オブジェクト・インスタンスに属していないことを検証します。(データベースの一意制約のビジネス・ロジック層に相当します。)エンティティ・オブジェクトの1つでキーが見つかった場合、TooManyObjectsException
がスローされます。検証チェックはエンティティ・キャッシュとデータベースの両方で行います。
一意キー検証を使用しても、データベースで重複行を防ぐことができない場合があります。また、2つのアプリケーション・モジュール・セッションが同時に同じキーのレコードを作成しようとする場合もあります。これを回避するには、適用する一意の制約に対して、データベースに一意索引を作成します。
始める前に:
組込み検証規則に関する一般知識があると役立つ場合があります。詳細は、「組込みの宣言的な検証規則の使用」を参照してください。
また、他の検証機能を使用して追加できる機能についても理解しておくと役立ちます。詳細は、「宣言的な検証の追加機能」を参照してください。
キー値の一意性を確認するには:
一意キー・バリデータの使用時の処理
Unique Key Validatorを使用すると、<UniqueKeyValidationBean>
タグがエンティティ・オブジェクトのXMLファイルに追加されます。次の例は、一意キー・バリデータのXMLを示しています。
<validation:UniqueKeyValidationBean Name="CustomerEORule0" KeyName="SCustomerIdPk"> <validation:OnAttributes> <validation:Item Value="Id"/> </validation:OnAttributes> </validation:UniqueKeyValidationBean>
比較に基づく検証方法
比較バリデータは、エンティティ属性と値の論理比較を実行します。比較バリデータの追加時に、演算子および比較対象を指定します。次のものを比較できます。
-
リテラル値
比較バリデータでリテラル値を使用すると、属性の値は指定したリテラル値と比較されます。この種類の比較を使用する場合は、データの型と書式を考慮することが重要です。リテラル値は、規則を適用するエンティティ属性のデータ型で指定した書式に準拠する必要があります。すべての場合において、型はエンティティ属性のタイプ・マッピングに対応します。
たとえば、列タイプDATEの属性は
oracle.jbo.domain.Date
クラスにマッピングされますが、これはjava.sql.TimeStamp
およびjava.sql.Date
によって受け入れられるのと同じ書式で日付と時間を受け入れます。書式マスクを使用することにより、属性の値の書式が指定されたリテラルに一致するよう指定できます。エンティティ・オブジェクトの属性タイプのマッピングの詳細は、「エンティティ・オブジェクト属性のデータベースおよびJavaデータ型を設定する方法」を参照してください。特定のタイプに必要なフォーマットの詳細は、Javadocのタイプ・クラスを参照してください。 -
問合せ結果
このタイプのバリデータを使用すると、バリデータが実行されるたびにSQL問合せが実行されます。バリデータは問合せ結果から最初の行を取得し、比較する値として問合せの最初の列(その最初の行の)の値を使用します。この問合せは内部にバインド変数を所有できないため、この機能が使用されるのは、現行の行の値に依存しないデータの1つの行の1つの列を選択するときのみです。
-
ビュー・オブジェクト属性
このタイプのバリデータを使用すると、バリデータが実行されるたびにビュー・オブジェクトのSQL問合せが実行されます。バリデータは問合せ結果から最初の行を取得し、比較する値としてその行から選択されたビュー・オブジェクト属性の値を使用します。ビュー・オブジェクトの名前付きバインド変数は値に関連付けできないので、そのような変数が利用できる値はデフォルト値のみです。したがって、この機能が使用されるのは、現行の行の値に依存しないデータの1つの行の属性を選択するときのみです。
-
ビュー・アクセッサ属性
ビュー・アクセッサの定義時、検証ビュー・オブジェクトのバインド変数に行固有の値を割り当てることができます。
-
式
式のオプションの詳細は、「ビジネス・ルールとトリガーでのGroovy式の使用」を参照してください。
-
エンティティ属性
エンティティ属性オプションは、エンティティ・レベルの比較バリデータに対してのみ利用可能です。
始める前に:
組込み検証規則に関する一般知識があると役立つ場合があります。詳細は、「組込みの宣言的な検証規則の使用」を参照してください。
また、他の検証機能を使用して追加できる機能についても理解しておくと役立ちます。詳細は、「宣言的な検証の追加機能」を参照してください。
比較に基づいて検証するには:
図10-2は、エンティティ・オブジェクト属性でエンティティ・レベルのCompareバリデータを使用する場合のダイアログを示しています。
比較に基づく検証時の処理
Compareバリデータを作成すると、<CompareValidationBean>
タグがエンティティ・オブジェクトのXMLファイルに追加されます。次の例は、OrdEO
エンティティ・オブジェクトのエンティティ・レベル・バリデータのXMLコードを示しています。
<validation:CompareValidationBean Name="OrdEO_Rule_0" ResId="oracle.summit.model.entities.OrdEO_Rule_0" OnAttribute="DateShipped" OperandType="ATTR" Inverse="false" CompareType="GREATERTHANEQUALTO" CompareValue="DateOrdered"> <validation:OnAttributes> <validation:Item Value="DateShipped"/> <validation:Item Value="DateOrdered"/> </validation:OnAttributes> </validation:CompareValidationBean>
値リストを使用した検証方法
リスト・バリデータにより、属性と値リスト(LOV)が比較されます。リスト・バリデータの追加時に、選択対象のリストのタイプを指定します。
-
リテラル値 - バリデータは、エンティティ属性が値リスト内(指定された場合はリスト外)にあることを確認します。
-
SQL問合せ - バリデータは、エンティティ属性が問合せの結果セットの最初の列内(指定された場合は列外)にあることを確認します。SQL問合せバリデータではバインド変数を使用できないので、表から問い合せる必要のある一定の小規模なリストでのみ使用する必要があります。問合せのすべての行はメモリーに取得されます。
-
ビューオブジェクト属性 - バリデータは、エンティティ属性がビュー属性内(指定された場合はビュー属性外)にあることを確認します。ビュー属性バリデータではバインド変数を使用できないため、表から問い合せる必要のある一定の小規模なリストでのみ使用する必要があります。問合せのすべての行はメモリーに取得されます。
-
ビュー・アクセッサ属性 - バリデータは、エンティティ属性がビュー・アクセッサ属性内(またはビュー・アクセッサ属性外)にあることを確認します。ビュー・アクセッサにはバインド変数が利用可能で、ユーザー・インタフェース上にLOVを作成するとビュー・アクセッサが必要になるため、ビュー・アクセッサはおそらく最も便利なオプションです。
ベスト・プラクティス:
リスト・バリデータの使用時は、ビュー・アクセッサ上でビュー基準を定義し、適宜ビュー・データのフィルタが行えるので、ビュー・アクセッサが最も便利です。一般的に、ビュー属性でLOVを定義する場合は、ビュー基準を設定してビュー・アクセッサを使用します。
始める前に:
組込み検証規則に関する一般知識があると役立つ場合があります。詳細は、「組込みの宣言的な検証規則の使用」を参照してください。
また、他の検証機能を使用して追加できる機能についても理解しておくと役立ちます。詳細は、「宣言的な検証の追加機能」を参照してください。
値リストを使用して検証するには:
図10-3は、ビュー・オブジェクト属性でListバリデータを使用する場合のダイアログを示しています。
リスト値を使用した検証時の処理
リスト値を使用して検証すると、<ListValidationBean>
タグがエンティティ・オブジェクトのXMLファイルに追加されます。次の例は、リスト・バリデータのビュー・オブジェクト属性を使用するCustomerEO.CountryId
属性を示しています。
<validation:ListValidationBean Name="CountryIdRule0" OnAttribute="CountryId" OperandType="JBO" Inverse="false" ListValue="oracle.summit.model.views.CountryVO.Id"/>
リスト・バリデータに関する必知事項
リスト・バリデータは、比較的小さい値セットに対して属性を検証するためのものです。「問合せ結果」または「ビュー・オブジェクト属性」タイプのリスト検証を選択する場合、検証対象の属性値がリスト内の属性と一致するかどうかを検証するためにメモリー内スキャンが実行される前に、問合せ結果のすべての行が取得されることに注意してください。バリデータのSQLまたはビュー・オブジェクト問合せによって実行される問合せでは、問合せのWHERE
句で検証される値は参照されません。
ユーザーが入力した製品コードが、膨大な量の製品が含まれる表に存在するかどうかを判別する必要がある場合、検証規則を使用することは効率的ではありません。かわりに、データベースに対して目的の検証問合せを実行するためにビュー・オブジェクトを使用してSQLベースの検証を効率的に実行するための技術は、「検証でのビュー・オブジェクトの使用」を参照してください。「バリデータを使用した属性値の検証」も参照してください。
また、比較する属性がキーの場合、リスト値の検証よりもキー存在バリデータが効率的であり、これらの選択を翻訳する必要がある場合、リテラルの選択のかわりに静的ビュー・オブジェクトを使用します。
値が特定の範囲内にあることを確認する方法
範囲バリデータは、エンティティ属性と値の範囲の論理比較を実行します。範囲バリデータの追加時に、最小および最大のリテラル値を指定します。範囲バリデータは、エンティティ属性の値が範囲内(指定された場合は、範囲外)にあることを検証します。
最小および最大値を動的に算出する必要がある場合や、エンティティの他の属性を参照する必要がある場合は、Script Expression Validatorを使用し、Groovy式を指定します。詳細は、「Groovy式でのビジネス・コンポーネントの参照に関する必知事項」と「Groovy式でのビジネス・コンポーネント属性値の操作に関する必知事項」を参照してください。
始める前に:
組込み検証規則に関する一般知識があると役立つ場合があります。詳細は、「組込みの宣言的な検証規則の使用」を参照してください。
また、他の検証機能を使用して追加できる機能についても理解しておくと役立ちます。詳細は、「宣言的な検証の追加機能」を参照してください。
特定の範囲内を検証するには:
範囲バリデータの使用時の処理
Rangeを検証すると、<RangeValidationBean>
タグがエンティティ・オブジェクトのXMLファイルに追加されます。次の例は、最小値が1で最大値が99のItemEO.Quantity
属性を示しています。
<validation:RangeValidationBean Name="QuantityRule0" OnAttribute="Quantity" OperandType="LITERAL" Inverse="false" MinValue="1" MaxValue="99"/>
バイトまたは文字数に対する検証方法
長さバリデータは、属性値の文字列長(文字またはバイト)が、指定した数より小さい、等しい、それより大きい、またはその範囲内かどうかを検証します。
始める前に:
組込み検証規則に関する一般知識があると役立つ場合があります。詳細は、「組込みの宣言的な検証規則の使用」を参照してください。
また、他の検証機能を使用して追加できる機能についても理解しておくと役立ちます。詳細は、「宣言的な検証の追加機能」を参照してください。
バイトまたは文字数を検証するには:
バイトまたは文字数に対する検証時の処理
長さを使用して検証すると、次の例に示すように、<LengthValidationBean>
タグがエンティティ・オブジェクトのXMLファイルに追加されます。たとえば、ユーザーがパスワードまたはPINを入力するフィールドがあり、アプリケーションによってそれが6文字以上、10文字以下であることを検証するとします。Length ValidatorでBetween演算子を使用し、最小値および最大値をそれぞれ設定します。
<validation:LengthValidationBean OnAttribute="pin" CompareType="BETWEEN" DataType="CHARACTER" MinValue="6" MaxValue="10" Inverse="false"/>
正規表現を使用した検証方法
正規表現バリデータは、Java正規表現によって指定されたマスクに対して属性値を比較します。
メタデータでパーソナライズできる式を作成する場合は、Script Expression Validatorを使用できます。詳細は、「ビジネス・ルールとトリガーでのGroovy式の使用」を参照してください。
始める前に:
組込み検証規則に関する一般知識があると役立つ場合があります。詳細は、「組込みの宣言的な検証規則の使用」を参照してください。
また、他の検証機能を使用して追加できる機能についても理解しておくと役立ちます。詳細は、「宣言的な検証の追加機能」を参照してください。
正規表現を使用して検証するには:
図10-4は、正規表現バリデータを選択して、Email
属性が事前定義されたEmail Address式に一致することを検証する場合のダイアログを示しています。
正規表現を使用した検証時の処理
正規表現を使用して検証すると、<RegExpValidationBean>
タグがエンティティ・オブジェクトのXMLファイルに追加されます。次の例は、正規表現に一致する必要のあるEmail
属性を示しています。
<validation:RegExpValidationBean Name="EmailPrimaryRule0" OnAttribute="EmailPrimary" Pattern="[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}" Flags="CaseInsensitive" Inverse="false"/>
Average、Count、またはSumを使用したコレクションの検証方法
コレクションのAverage、Count、Sum、Min、またはMaxに対してコレクション検証を使用できます。このバリデータは、エンティティ・レベルでのみ使用できます。このバリデータは、子エンティティ(アソシエーションの多数の端)に対するエンティティ・アクセッサを介した、関連エンティティのコレクションに対する集計計算の検証に便利です。コレクション・バリデータを定義するには、アソシエーション・アクセッサを選択する必要があります。
始める前に:
組込み検証規則に関する一般知識があると役立つ場合があります。詳細は、「組込みの宣言的な検証規則の使用」を参照してください。
また、他の検証機能を使用して追加できる機能についても理解しておくと役立ちます。詳細は、「宣言的な検証の追加機能」を参照してください。
集約計算を使用して検証するには:
コレクション検証の使用時の処理
コレクション・バリデータを使用して検証すると、次の例のように、<CollectionValidationBean>
タグがエンティティ・オブジェクトのXMLファイルに追加されます。
<validation:CollectionValidationBean Name="OrdEORule01" Accessor="ItemEO" CollAttribute="Quantity" OperandType="LITERAL" Inverse="false" CompareType="GREATERTHAN" CompareValue="5" Operation="min"/>
キーの存在の判別方法
キー存在バリデータは、キー値(主キー、外部キー、代替キーのいずれか)が存在するかどうか判別するために使用されます。
キー存在バリデータの使用には、次のようないくつかの利点があります。
-
キー存在バリデータは、最初にキャッシュをチェックし、必要な場合にのみデータベースをチェックするため、パフォーマンスが向上します。
-
キー存在バリデータはキャッシュを使用するため、現行トランザクションに追加されているが、まだデータベースにコミットされていないキー値を検出します。たとえば、新規の
Department
を追加してから、そこにEmployee
をリンクします。
始める前に:
組込み検証規則に関する一般知識があると役立つ場合があります。詳細は、「組込みの宣言的な検証規則の使用」を参照してください。
また、他の検証機能を使用して追加できる機能についても理解しておくと役立ちます。詳細は、「宣言的な検証の追加機能」を参照してください。
値の存在を判別するには:
図10-5は、PersonEO
エンティティ・オブジェクトに入力したMembershipId
がMembershipBaseEO
エンティティ・オブジェクトに存在するかどうかを検証するキー存在バリデータを示しています。
図10-5 エンティティ属性に対するキー存在バリデータ
![この図は周囲のテキストで説明しています この図は周囲のテキストで説明しています](img/key_exists.png)
キー存在バリデータの使用時の処理
キー存在バリデータを使用すると、次の例のように、<ExistsValidationBean>
タグがエンティティ・オブジェクトのXMLファイルに作成されます。
<validation:ExistsValidationBean Name="CustomerId_Rule_0" ResId="oracle.summit.model.entities.OrdEO.CustomerId_Rule_0" OperandType="EO" AssocName="oracle.summit.model.entities.assoc.SOrdCustomerIdFkAssoc"/>
宣言的バリデータとビュー・アクセッサに関する必知事項
宣言的バリデータを使用する場合は、想定される入力値で検証がどのように実行されるかを考慮する必要があります。宣言的バリデータとビュー・アクセッサを組み合せることにより、簡単かつ強力なコーディングの代用として機能します。ただし、これらを組み合せると強力になる反面、データ構成がパフォーマンスに与える影響も考慮する必要があります。
次のようなシナリオを検討します。
-
Product
属性とRequestType
属性を持つServiceRequestEO
エンティティ・オブジェクト、およびRequestTypeVO
ビュー・オブジェクトへのアクセスを可能にするビュー・アクセッサ -
Product
属性をバインド・パラメータとして指定する問合せを持つRequestTypeVO
ビュー・オブジェクト
RequestType
の有効なリストは、Product
によって変わります。このため、RequestType
属性を検証するには、ビュー・アクセッサを使用するリスト・バリデータを使用します。
最初に、新規サービス・リクエストのセットを追加します。最初のサービス・リクエスト(行)に対して、リスト・バリデータはProduct
属性の値をビュー・アクセッサに追加して実行します。次に、後続の各サービス・リクエストに対して、Product
属性の新しい値と現時点でバインドされている値を比較します。
-
Product
の値が一致する場合、現在のRowSetオブジェクトは維持されます。 -
Product
の値が変更されている場合、新しい値がバインドされ、ビュー・アクセッサが再実行されます。
次に、想定される入力データの構成を検討します。たとえば、入力データに同じ製品が複数回現れるとします。受注品のデータを検証すると、次のようになっているとします。
-
ドライヤー(最初の問合せ)
-
洗濯機(ビュー・アクセッサを再実行)
-
食器洗浄機(ビュー・アクセッサを再実行)
-
洗濯機(ビュー・アクセッサを再実行)
-
ドライヤー(ビュー・アクセッサを再実行)
この場合、バリデータは問合せを5回実行し、個別の行セットを3つ取得します。また、RequestTypeVO
にORDER BY
句を追加して、Product
別にソートすることもできます。この場合、バリデータは洗濯機とドライヤーに対して問合せをそれぞれ1回のみ実行します。
-
食器洗浄機(最初の問合せ)
-
ドライヤー(ビュー・アクセッサを再実行)
-
ドライヤー
-
洗濯機(ビュー・アクセッサを再実行)
-
洗濯機
このサイズのデータセットでは違いがあまり出ませんが、データセットのサイズが膨大になりユーザー数が多くなると、その差が大きな問題となります。ORDER BY
句ですべての問題に対応できるとはかぎりませんが、この例は、データ構成がパフォーマンスにどのように影響を与えるかを示しています。
エンティティ・レベルのトリガーの使用方法
ADFビジネス・コンポーネントを使用すると、エンティティ・オブジェクトのライフサイクルでトリガーを適用できます。トリガーは、削除の前、削除の後、挿入操作の前などの設定されたライフサイクル・イベント時に実行されます。
エンティティ・レベルのトリガーを使用すると、挿入操作の前や削除の後など、エンティティ・オブジェクトのライフサイクル内のトリガー・ポイントに対応して実行される式を実装できます。
たとえば、エンティティ・オブジェクトの挿入前やエンティティ・オブジェクトの更新後に、属性の値を評価またはアサートできます。使用可能なトリガー・ポイントのリストは、オンライン・ヘルプを参照してください。
エンティティ・レベルのトリガーを使用したビジネス・ルールの実装方法
Groovyスクリプトを使用して、エンティティ・レベルのトリガーに対応して実行されるビジネス・ルールを実装できます。
エンティティ・レベルのトリガーについて理解しておくと役立つ場合があります。「エンティティ・レベルのトリガーの使用方法」を参照してください。
また、他の検証機能を使用して追加できる機能についても理解しておくと役立ちます。「宣言的な検証の追加機能」を参照してください。
- 「アプリケーション」ウィンドウで、トリガーを追加するエンティティ・オブジェクトをダブルクリックします。
- 概要エディタで、「ビジネス・ルール」ナビゲーション・タブをクリックします。
- 「ビジネス・ルール」ページで、エンティティ・レベルのトリガーのノードを選択し、「新規トリガーの作成」アイコンをクリックします。
- 「タイプ」ドロップダウン・リストから適切なトリガー・ポイントを選択します。
- Groovy式を入力します。
- 「失敗処理」タブをクリックして、式が失敗した場合にユーザーに表示されるエラー・メッセージを入力または選択します。
エンティティ・レベルのトリガーの作成時の処理
トリガーを作成すると、次の例に示すように、<Trigger>
タグがエンティティ・オブジェクトのXMLファイルに追加されます。
<Trigger Name="BeforeUpdate"> <validation:ExpressionValidationBean Name="BeforeUpdateExpression0" OperandType="EXPR" Inverse="false"> <validation:TransientExpression Name="ValidationRuleScript" trustMode="untrusted" hasReturn="false" CodeSourceName="ItemEORow"/> </validation:ExpressionValidationBean> </Trigger>
ビジネス・ルールとトリガーでのGroovy式の使用
Groovy式を使用してビジネス・ルールおよびトリガーを構築できます。このような式は、ADFエンティティ・オブジェクトのXML定義の一部として、またエンティティ・オブジェクトに関連付けられた.bcs
ファイルに格納されます。
Groovy式はJavaのようなスクリプト・コードで、エンティティ・オブジェクトのXML定義とそのエンティティ・オブジェクトに関連する.bcs
ファイルに格納されます。Groovy式は.bcs
ファイルに格納されるため、このファイルで式の値を変更できます。
エンティティ・オブジェクトのビジネス・ロジックでのGroovyスクリプトの使用方法の詳細は、「ビジネス・コンポーネントでのGroovyスクリプト言語の使用」を参照してください。
Groovy式でのエンティティ・オブジェクト・メソッドの参照方法
現在のオブジェクトのsource
プロパティを使用すると、現在のエンティティ・インスタンスでメソッドをコールできます。source
プロパティでは、エンティティ・インスタンスにアクセスできます。
メソッドがブール型以外で、メソッド名が引数なしのgetXyzAbc()
の場合、XyzAbc
という名前のプロパティのようにその値にアクセスします。ブール値プロパティの場合は、同じ条件が当てはまりますが、JavaBeanのgetterメソッドの命名パターンが変更され、getXyzAbc()
ではなくisXyzAbc()
を再認識します。エンティティ・オブジェクトのメソッドがJavaBeanのgetterメソッドの命名パターンに一致しない場合や、1つ以上の引数を使用する場合は、完全名を使用したメソッドのようにコールする必要があります。
たとえば、次の例に示すように、4つのメソッドを持つエンティティ・オブジェクトがあるとします。
public boolean isNewRow() { System.out.println("## isNewRow() accessed ##"); return true; } public boolean isNewRow(int n) { System.out.println("## isNewRow(int n) accessed ##"); return true; } public boolean testWhetherRowIsNew() { System.out.println("## testWhetherRowIsNew() accessed ##"); return true; } public boolean testWhetherRowIsNew(int n) { System.out.println("## testWhetherRowIsNew(int n) accessed ##"); return true; }
次のGroovy検証条件では、この例に示すように、すべてを実行し、そのうちの1つは2回実行します。
newRow && source.newRow && source.isNewRow(5) && source.testWhetherRowIsNew() && source.testWhetherRowIsNew(5)
この例を実行してエンティティ検証を適用すると、次の診断結果がログ・ウィンドウに表示されます。
## isNewRow() accessed ## ## isNewRow() accessed ## ## isNewRow(int n) accessed ## ## testWhetherRowIsNew() accessed ## ## testWhetherRowIsNew(int n) accessed ##
名前がJavaBeansプロパティのgetterメソッドの命名パターンに一致するメソッドの参照では、構文にほとんど差がありません。newRow
とsource.newRow
は、両方とも、引数のないブール値のJavaBeans getterスタイル・メソッドにアクセスします。testWhetherRowIsNew
メソッドは、JavaBeansのgetterメソッドのネーミング・パターンに一致せず、3番目のisNewRow()
メソッドは引数を使用するため、完全名を使用するメソッドのようにコールする必要があります。
true/false式を使用した検証方法
Groovy式を使用してtrue/false文を返すことができます。スクリプト式バリデータでは、必ず式がtrue
またはfalse
を返す必要があり、そうでなければadf.error.raise
/warn()
メソッドがコールされます。この機能の一般的な用途は、属性値の検証です(アカウント番号が有効であるかの確認など)。
ノート:
adf.error.raise()
メソッドを使用することにより(単純にtrue
またはfalse
を返すかわりに)、ユーザーに表示するメッセージ・テキストを定義でき、エンティティレベル・バリデータを特定の属性に関連付けることができます。詳細は、「Groovyを使用して条件付きでエラー・メッセージを呼び出す方法」を参照してください。
始める前に:
検証規則でのGroovyの使用方法に関する知識があると役立つ場合があります。詳細は、「ビジネス・ルールとトリガーでのGroovy式の使用」を参照してください。
また、他の検証機能を使用して追加できる機能についても理解しておくと役立ちます。詳細は、「宣言的な検証の追加機能」を参照してください。
true/false式を使用して検証するには:
次のGroovyスクリプトの例では、広範に使用されているチェックサムのLuhnアルゴリズムに基づいて口座番号を検証します。
@ValidatorExpression(name="PaymentOptionIdRule0", attributeName="PaymentOptionId") def PaymentOptionId_PaymentOptionIdRule0_ValidationRuleScript_ValidationRule() { String acctnumber = newValue; sumofdigits = 0; digit = 0; addend = 0; timesTwo = false; range = acctnumber.length()-1..0 range.each {i -> digit = Integer.parseInt (acctnumber.substring (i, i + 1)); if (timesTwo) { addend = digit * 2; if (addend > 9) { addend -= 9; } } else { addend = digit; } sumofdigits += addend; timesTwo = !timesTwo; } modulus = sumofdigits % 10; return modulus == 0; }
Groovy式の追加時の処理
Groovy式を作成すると、エンティティ・オブジェクトのXMLコンポーネントに保存されます。次の例は、エンティティ・オブジェクトのDateOrdered
属性を示しています。Groovy式は<validation:ExpressionValidationBean>
タグで囲まれています。XML定義のCodeSourceName="OrdEORow”
が示すとおり、GroovyスクリプトはOrdEO.bcs
ファイルに格納されています。
<Attribute Name="DateOrdered" ColumnName="DATE_ORDERED" SQLType="TIMESTAMP" Type="java.sql.Date" ColumnType="DATE" TableName="S_ORD"> <DesignTime> <Attr Name="_DisplaySize" Value="7"/> </DesignTime> <validation:ExpressionValidationBean Name="DateOrderedRule0" OperandType="EXPR" Inverse="false"> <validation:TransientExpression Name="ValidationRuleScript" trustMode="untrusted" CodeSourceName="OrdEORow"/> </validation:ExpressionValidationBean> </Attribute>
図10-6は、「検証規則の編集」ダイアログの検証式を示しています。
検証実行のトリガー
ADFビジネス・コンポーネントを使用すると、属性レベルおよびエンティティ・レベルの検証を定義できます。
JDeveloperでは、検証をトリガーする属性を選択できるため、トリガー属性のいずれかの内容が保証されない場合にのみ検証実行が発生します。JDeveloperの以前のリリースでは、全体としてのエンティティの内容が保証されない場合は常に属性に対してエンティティ・レベルのバリデータが起動されていました。この機能については、「検証を起動する属性の指定方法」を参照してください。
JDeveloperでは、バリデータ実行の事前条件を指定することもできます(「検証の事前条件の設定方法」を参照)。また、トランザクション・レベルの検証を設定することもできます(「トランザクション・レベルの検証の設定方法」を参照)。
検証を起動する属性の指定方法
エンティティ・レベルでバリデータを定義する場合、変更時にバリデータの実行をトリガーする、エンティティ・オブジェクトの1つ以上の属性を選択するオプションがあります。
ノート:
1つの属性の有効性が別の属性に依存する場合、検証は属性の検証ではなくエンティティの検証として実行する必要があります。エンティティ・レベルや属性レベルで検証実行の順序を設定できます。
依存属性を1つ以上指定しないと、エンティティの内容が保証されていない場合にバリデータが常に起動します。必要な場合にのみ検証を実行することで、アプリケーションをより高性能にします。
始める前に:
検証規則のトリガー方法に関する知識があると役立つ場合があります。詳細は、「検証実行のトリガー」を参照してください。
また、他の検証機能を使用して追加できる機能についても理解しておくと役立ちます。詳細は、「宣言的な検証の追加機能」を参照してください。
検証を起動する属性を指定するには:
- 「アプリケーション」ウィンドウで、目的のエンティティ・オブジェクトをダブルクリックします。
- 概要エディタで「ビジネス・ルール」ナビゲーション・タブをクリックし、「エンティティ」ノードを選択して、「編集」アイコンをクリックします。
- 「検証規則の編集」ダイアログで、「検証実行」タブをクリックします。
- 検証を起動する属性を選択します。
- 「OK」をクリックします。
たとえば、SummitADF
アプリケーション・ワークスペースで、OrdEO
エンティティ・オブジェクトにはDateOrdered
属性より後のDateShipped
属性が必要なエンティティ・レベルのバリデータがあります。図10-7に示すように、このバリデータはDateShipped
属性またはDateOrdered
属性の変更時にのみ、エンティティ・オブジェクト上で実行するように設定されています。
属性のトリガーによる検証実行制約時の処理
「検証ルールの編集」ダイアログの「検証実行」タブでトリガー属性を指定すると、JDeveloperは<validation:OnAttributes>
タグを、エンティティ・オブジェクトのXMLファイルのバリデータ定義に追加します。次の例は、コアSummit ADFサンプル・アプリケーションにおけるOrdEO
エンティティ・オブジェクトのエンティティ・レベルのバリデータのXMLコードを示しています。
<validation:CompareValidationBean Name="OrdEO_Rule_0" ResId="oracle.summit.model.entities.OrdEO_Rule_0" OnAttribute="DateShipped" OperandType="ATTR" Inverse="false" CompareType="GREATERTHANEQUALTO" CompareValue="DateOrdered"><validation:OnAttributes>
<validation:Item
Value="DateShipped"/>
<validation:Item
Value="DateOrdered"/>
</validation:OnAttributes>
</validation:CompareValidationBean>
検証の事前条件の設定方法
「検証実行」タブ(検証規則の追加/編集ダイアログ)で、事前条件として機能するGroovy式を追加できます。「条件付実行式」ボックスに式を入力すると、条件がTrue
に評価された場合のみ、バリデータが実行されます。
ベスト・プラクティス:
一意キー・バリデータの事前条件の追加が可能ですが、ベスト・プラクティスではありません。一意キー・バリデータが起動できない場合でもキャッシュの一貫性チェックが実行されるため、エラーが返されます。通常は、バリデータおよびわかりやすいエラー・メッセージを追加するのが適切です。
トランザクション・レベルの検証の設定方法
トランザクション・レベル(エンティティ・レベルではなく)での検証は、すべてのエンティティ・レベルの検証の実行後に実行されます。このため、バリデータがプロセスの終了時に実行されることを確認する場合に便利です。
さらにKey Existsバリデータをトランザクション・レベルで実行すると、エンティティごとではなく、トランザクション内の全エンティティ(同じ型の)に対して1度だけ実行されるので、 大量のトランザクションでは高いパフォーマンスが得られます。これにより、バリデータをデータベースに使用する場合はパフォーマンスの改善につながります。
ノート:
トランザクション・レベルの検証は、Key ExistsおよびMethodエンティティ・バリデータにのみ適用できます。
始める前に:
検証規則のトリガー方法に関する知識があると役立つ場合があります。詳細は、「検証実行のトリガー」を参照してください。
また、他の検証機能を使用して追加できる機能についても理解しておくと役立ちます。詳細は、「宣言的な検証の追加機能」を参照してください。
エンティティ・レベルまたはトランザクション・レベルの検証を指定するには:
- 「アプリケーション」ウィンドウで、目的のエンティティ・オブジェクトをダブルクリックします。
- 概要エディタで「ビジネス・ルール」ナビゲーション・タブをクリックし、エンティティ・レベルの検証ルールを選択して、「編集」アイコンをクリックします。
- 「検証規則の編集」ダイアログで、「検証実行」タブをクリックします。
- 「エンティティ・レベルで実行」または「トランザクション・レベルの遅延実行」を選択します。
- 「OK」をクリックします。
検証エラー・メッセージの作成
ADFビジネス・コンポーネントを使用すると、問題およびトラブルシューティング・ヒントについて一目瞭然の情報をエンド・ユーザーに提供するテキストを入力して、検証エラー・メッセージを作成できます。
検証エラー・メッセージはユーザーにとって重要な情報であり、メッセージは不具合やその修正方法を伝達する必要があります。
バリデータとトリガーのエラー・メッセージの作成方法
検証ルールまたはトリガーを作成または編集する場合、ユーザーがエラーの原因を判断するために有用なテキストを入力できます。
始める前に:
検証規則のエラー・メッセージに関する知識があると役立つ場合があります。詳細は、「検証エラー・メッセージの作成」を参照してください。
また、他の検証機能を使用して追加できる機能についても理解しておくと役立ちます。詳細は、「宣言的な検証の追加機能」を参照してください。
バリデータまたはトリガーのエラー・メッセージを作成するには:
検証メッセージのローカライズ方法
エラー・メッセージは翻訳可能文字列であり、エンティティ・オブジェクトのメッセージ・バンドル・クラスの翻訳可能UIコントロール・ヒントと同じように管理されます。メッセージ・バンドル・クラス内の定義済規則のエラー・メッセージを表示するには、そのバリデータに関するXMLドキュメント・エントリのResId
プロパティに対応するメッセージ・バンドルのString
キーを探します。たとえば、次の例は、NAME_CANNOT_BEGIN_WITH_U
キーがデフォルト・ロケールのエラー・メッセージとともに表示されるメッセージ・バンドルを示しています。
アプリケーションのリソース・バンドルは、リスト・リソース・バンドル(次の例を参照)、プロパティ・バンドル、またはXLIFFリソース・バンドルとして作成できます。リソース・バンドルでの変換可能な文字列の使用の詳細は、「リソース・バンドルの使用」を参照してください。
package devguide.advanced.customerrors; import java.util.ListResourceBundle; public class CustomMessageBundle extends ListResourceBundle { private static final Object[][] sMessageStrings = new String[][] { // other strings here {"NAME_CANNOT_BEGIN_WITH_U", "The name cannot begin with the letter u!"}, // other strings here }; // etc. }
Groovyを使用して条件付きでエラー・メッセージを呼び出す方法
adf.error.raise()
およびadf.error.warn()
メソッドを使用して、Groovy式の分岐に応じて様々なエラー・メッセージを条件付きで呼び出すことができます。たとえば、属性値がxの場合は次のように検証し、検証が失敗した場合はエラーメッセージAを呼び出し、一方、属性値がyの場合は別の検証を実行し、検証が失敗した場合はエラーメッセージBを呼び出します。
式でfalse
が戻される(raise()
メソッドを使用して特定のエラー・メッセージが呼び出されるのに対して)場合、バリデータは、そのバリデータに関連付けられた最初のエラー・メッセージをコールします。
raise()
メソッドの構文は必須パラメータを1つ(メッセージ・バンドルから使用するためのmsgId
)利用し、オプションでattrName
パラメータを利用することができます。AttrName
に渡すと、検証がエンティティに割り当てられている場合でも、エラーはその属性に関連付けられます。
例外をスローするか、処理を継続するかに応じて、adf.error.raise()
またはadf.error.warn()
のいずれかのメソッドを使用できます(「検証例外の重大度レベルの設定」を参照)。
エラー・メッセージにGroovy式を埋め込む方法
バリデータのエラー・メッセージには、実行時にサーバーによって解決できる埋込み式を含めることができます。この機能にアクセスするには、Groovy式の結果を表示させるエラー・メッセージ・テキストに名前付きトークン{#}({2}
や{errorParam}
など)を入力するのみです。
「検証規則の編集」ダイアログの「失敗処理」タブで、エラー・メッセージのテキストにトークンを入力すると、ダイアログの下部の「トークン・メッセージ式」表で行が表示され、トークンのGroovy式を入力できます。図10-8は、メッセージ・トークンを含むOrdEO
エンティティ・オブジェクトの検証ルールの失敗メッセージを示しています。
図10-8 失敗メッセージでのメッセージ・トークンの使用
![この図は周囲のテキストで説明しています この図は周囲のテキストで説明しています](img/validationmsgtokens.png)
図10-8に示された式は、指定したフィールドのラベルを返すGroovy式です。Groovy式を使用して属性値やその他のビジネス・コンポーネント・オブジェクトにアクセスすることもできます。たとえば、Groovy式newValue
を使用して入力された値を戻すことができます。
ビュー・アクセッサから値を取得するためのGroovy構文は、accessorName
.currentRow.
AttributeName
です。たとえば、Groovy式MyEmpAccessor.currentRow.Job
は、MyEmpAccessor
ビュー・アクセッサの現在の行のJob
属性値を返します。
次の例のように複雑なGroovy式を使用して、OrdEO
エンティティ・オブジェクト内のPaymentTypeId
属性のList検証ルールのエラー・メッセージに式を表示することもできます。
cr = CustomerEO.CreditRatingId ratings = [1, 2] if (cr in ratings) {return true} else {return false}
Groovyを使用したビジネス・コンポーネント・オブジェクトへのアクセスの詳細は、「ビジネス・コンポーネントでのGroovyスクリプト言語の使用」を参照してください。
検証例外の重大度レベルの設定
ADFビジネス・コンポーネントを使用すると、検証例外の重大度レベルを「情報警告」または「エラー」として設定できます。後者のレベルに設定すると、エンド・ユーザーは問題を修正しないと続行できません。
検証例外の重大度レベルについて、「情報警告」および「エラー」の2つのレベルを設定できます。重大度レベルを「情報警告」に設定すると、エラー・メッセージが表示されますが、処理は継続します。検証レベルを「エラー」に設定すると、エラーが修正されるまでユーザーは処理を続行できません。
通常、検証例外には「エラー」レベルを使用するため、これがデフォルト設定です。ただし、ユーザーが特定の機密取扱い資格を保持する場合は、情報警告メッセージを実装できます。たとえば、店長は事務員が同じことをした場合に、エラーとして表示されるように変更できます。
重大度レベルが「情報警告」に設定されている場合、エラー・アイコンではなく警告アイコンとともにエラー・メッセージが表示され、警告を確認した後に変更の保存に進むことができます。
検証例外の重大度レベルを設定するには、「検証ルールの追加」ダイアログの「失敗処理」タブを使用します。
検証例外の重大度レベルを設定するには:
- 「アプリケーション」ウィンドウで、目的のエンティティ・オブジェクトをダブルクリックします。
- 概要エディタで、「ビジネス・ルール」ナビゲーション・タブをクリックします。
- 「ビジネス・ルール」ページで、既存の検証規則を選択して「編集」アイコンをクリックするか、「追加」アイコンをクリックして新規の規則を作成します。
- 検証規則の追加/編集ダイアログで、「失敗処理」タブをクリックし、「エラー」または「情報警告」のいずれかのオプションを選択します。
- 「OK」をクリックします。
SQLでのバルク検証
ADFビジネス・コンポーネントには、バッチロード・アプリケーションのパフォーマンスを向上させるためのバルク検証機能が用意されています。検証は、主キー、代替キーおよび外部キーに対して適用されます。
データ同期プログラムなどのバッチロード・アプリケーションのパフォーマンスを向上させるため、Oracle ADFでは、主キー(代替キーを含む)および外部キーにバルク検証を採用しています。
トランザクションがコミットするまで検証を遅延するようにキー存在バリデータを構成している場合や、ADFビジネス・コンポーネントのサービス・レイヤーのprocess
XXX
メソッドで行が更新または挿入されている場合、検証キャッシュが事前ロードされます。この動作は通常の行ごとの導出および検証ロジックを使用しますが、データベースに問い合せる前にメモリー・キャッシュをチェックする検証ロジックを使用します。パフォーマンスは、インバウンド・データに基づいてバルクSQL操作を使用するメモリー・キャッシュの事前ロードによって向上します。