8 ビュー・インスタンスの問合せのテスト

この章では、JDeveloperで提供されるOracle ADFモデル・テスターを使用して、ADFビュー・オブジェクト問合せ結果を対話的にテストする方法について説明します。この章では、ADFビジネス・コンポーネントAPIを使用してJDeveloper外部のテスト・クライアントに含まれるビュー・オブジェクト・インスタンスにアクセスする方法についても説明します。

この章の内容は次のとおりです。

ビュー・インスタンスの問合せについて

Oracle ADFモデル・テスターを使用してデータ・モデルの対話型ADFアプリケーション・モジュール・テストを実行します。

JDeveloperには、アプリケーション・ユーザー・インタフェースを使用せず、またはテスト・クライアントのプログラムを記述せずに、データ・モデルのすべての面をテストできるようにする、対話型アプリケーション・モジュール・テスト・ツールが用意されています。多くの場合、Oracle ADFモデル・テスターを実行すると、開発時にビジネス・サービスのデータ機能を最も迅速に実行できます。

ノート:

アプリケーション・モジュールをプログラムによってテストする場合は、テスト・クライアントを記述できます。「コマンドラインJavaテスト・クライアントの作成方法」を参照してください。

ビュー・インスタンスのユースケースと例

Oracle ADFモデル・テスターを使用すると、独自のカスタム・ユーザー・インタフェースを作成する前に、エンド・ユーザーとアプリケーション・モジュールのデータ・モデルとの対話をシミュレートできます。UIページを作成したも、Oracle ADFモデル・テスターは問題発生時の診断に役立ちます。Oracle ADFモデル・テスターで問題を再現して、問題がアプリケーションのビュー・レイヤーまたはコントローラ・レイヤーにあるのか、あるいはビジネス・サービス・レイヤーのアプリケーション・モジュール自体にあるのかを確認できます。

ビュー・インスタンスのテストの追加機能

ビュー・インスタンスで作業を開始する前に、その他のOracle ADF機能を理解しておくと役に立つ場合があります。次に、関連する他の機能へのリンクを示します。

ビュー・インスタンスをテストするためのアプリケーション・モジュールの作成

ADFアプリケーション・モジュールを定義し、ビュー・オブジェクト・インスタンスを使用してデータ・モデルを構築します。必要に応じて、Oracle ADFモデル・テスターを使用してアプリケーション・モジュールをテストします。

データ・モデル・プロジェクトで作成したビュー・オブジェクトをテストするには、テスト対象のビュー・オブジェクトのインスタンスを定義するアプリケーション・モジュールを作成する必要があります。アプリケーション・モジュールは、Oracle ADFモデル・テスター(またはUIクライアント)がアプリケーション・データの操作に使用するトランザクション・コンポーネントです。アプリケーション・モジュールで使用される一連のビュー・オブジェクトは、それ自体のデータ・モデル、つまり、クライアントがユーザー・インタフェースを介して表示および操作できる一連のデータを定義します。

アプリケーション・モジュールに追加したビュー・オブジェクトをテストするには、「アプリケーション」ウィンドウからアクセスできるOracle ADFモデル・テスターを使用します。Oracle ADFモデル・テスターの使用方法の詳細は、「Oracle ADFモデル・テスターを使用したビュー・オブジェクト・インスタンスのテスト」を参照してください。

個別のビュー・オブジェクト・インスタンスを使用したアプリケーション・モジュールの作成方法

個別のビュー・オブジェクトのインスタンスを定義するアプリケーション・モジュールを作成するには、「新規ギャラリ」から使用できる「アプリケーション・モジュールの作成」ウィザードを使用します。

始める前に:

アプリケーション・モジュールの知識があると役立ちます。詳細は、「ビュー・インスタンスをテストするためのアプリケーション・モジュールの作成」を参照してください。

他のOracle ADF機能を使用して追加できる機能を理解しておくことも役立ちます。詳細は、「ビュー・インスタンスのテストの追加機能」を参照してください。

次のタスクを完了する必要があります。

個別のビュー・オブジェクト・インスタンスをテストするためのアプリケーション・モジュールを作成するには:

  1. 「アプリケーション」ウィンドウで、アプリケーション・モジュールを作成するプロジェクトを右クリックし、「新規」「アプリケーション・モジュール」の順に選択します。
  2. 「アプリケーション・モジュールの作成」ウィザードの「名前」ページで、パッケージ名およびアプリケーション・モジュール名を指定します。「次へ」をクリックします。
  3. 「データ・モデル」ページで、以前に定義したビュー・オブジェクトのインスタンスを指定し、このビュー・オブジェクト・インスタンスの名前をクライアントで認識される名前とまったく同じ名前に編集します。次に、「終了」をクリックします。

    「データ・モデル」ページに表示されるデフォルトのインスタンス名を受け入れるかわりに、インスタンス名をわかりやすい名前に変更できます(たとえば、デフォルト名OrderItems1のかわりに、AllOrderItemsに名前を変更できます)。

マスター/ディテール・ビュー・オブジェクト・インスタンスを使用したアプリケーション・モジュールの作成方法

「アプリケーション・モジュールの作成」ウィザードを使用して、ビュー・オブジェクトが表すマスター/ディテール関係に基づいてアプリケーション・モジュールのビュー・オブジェクトの階層を作成することもできます。

始める前に:

アプリケーション・モジュールの知識があると役立ちます。詳細は、「ビュー・インスタンスをテストするためのアプリケーション・モジュールの作成」を参照してください。

他のOracle ADF機能を使用して追加できる機能を理解しておくことも役立ちます。詳細は、「ビュー・インスタンスのテストの追加機能」を参照してください。

次のタスクを完了する必要があります。

ビュー・オブジェクト関連に基づいてアプリケーション・モジュールを作成するには:

  1. 「アプリケーション」ウィンドウで、アプリケーション・モジュールを作成するプロジェクトを右クリックし、「新規」を選択します。
  2. 「新規ギャラリ」で、「ビジネス層」を展開し、「ADFビジネス・コンポーネント」を選択してから「アプリケーション・モジュール」を選択し、「OK」をクリックします。
  3. 「アプリケーション・モジュールの作成」ウィザードで、「データ・モデル」ノードを選択します。
  4. 「使用可能なビュー・オブジェクト」リストで、アクティブに調整するマスターとするビュー・オブジェクトのインスタンスを選択します。

    リスト内のマスター・ビュー・オブジェクトには、このビュー・オブジェクトにビュー・リンクがあることを示すプラス記号が表示されます。ビュー・リンクは、マスター/ディテール階層の定義に必要です。

    たとえば、図8-1は、選択したPersonsVOと、「新規ビュー・インスタンス」フィールドで名前を変更したAuthenticatedUserを示しています。

    図8-1 選択したマスター・ビュー・オブジェクト

    図8-1の説明が続きます
    「図8-1 選択したマスター・ビュー・オブジェクト」の説明
  5. 選択したマスター・ビュー・オブジェクトを「データ・モデル」リストに移動します。

    たとえば、図8-2は、「データ・モデル」リストに追加した後の新規作成したマスター・ビュー・インスタンスAuthenticatedUserを示しています。

    図8-2 作成したマスター・ビュー・インスタンス

    図8-2の説明が続きます
    「図8-2 作成したマスター・ビュー・インスタンス」の説明
  6. 「データ・モデル」リストで、新規作成したマスター・ビュー・インスタンスを選択してハイライトしておきます。これは、追加するディテール・ビュー・インスタンスのターゲットになります。次に、「使用可能なビュー・オブジェクト」リストで、マスター・ビュー・オブジェクトの下のディテール・ビュー・オブジェクトを特定して選択します。

    たとえば、図8-3は、マスター・ビュー・オブジェクトPersonsVOの下にある、OrdersVO via PersonsToOrdersという名前のディテール・ビュー・オブジェクトOrdersVOを示しています。この名前はビュー・リンクPersonsToOrdersを表し、PersonsVOOrdersVO間のマスター/ディテール階層を定義します。ディテール・ビュー・インスタンスの名前はMyOrdersに変更されます。

    図8-3 選択したディテール・ビュー・オブジェクト

    図8-3の説明が続きます
    「図8-3 選択したディテール・ビュー・オブジェクト」の説明
  7. 追加したマスター・インスタンスにディテール・インスタンスを追加するには、「データ・モデル」リストで選択したマスター・ビュー・インスタンスの下に、ディテール・ビュー・オブジェクトを移動します。

    図8-4は、データ・モデルにAuthenticatedUserのディテールとして新規作成したディテール・ビュー・インスタンスMyOrdersを示しています。

    図8-4 作成したマスター・ビュー・インスタンス

    図8-4の説明が続きます
    「図8-4 作成したマスター・ビュー・インスタンス」の説明
  8. 別の階層レベルを追加するには、新しく追加したディテール・インスタンスを「データ・モデル」リストで選択してから、新しいディテール・インスタンスを移動します。このディテール・インスタンスは、前に追加したディテール・インスタンスとマスター/ディテール関係を持ちます。

    データ・モデルには、ビュー・オブジェクト関係でサポートされているだけの数の階層レベルを含めることができます。たとえば、図8-5には、「データ・モデル」リストに、インスタンスAuthenticatedUser (PersonsVOから名前を変更)がMyOrders (OrdersVO via PersonsToOrdersから名前を変更)のマスターとして、またこれがMyOrderItems (OrderItemsVO via OrdersToOrderItemsから名前を変更)のマスターとして表示されています。ディテール・ビュー・オブジェクトのMyOrderItemsは、別のビュー・オブジェクトのマスターではないため、階層の最後のレベルになります。

    図8-5 作成したマスター/ディテール/ディテール階層

    この図は周囲のテキストで説明しています

Oracle ADFモデル・テスターを使用したビュー・オブジェクト・インスタンスのテスト

Oracle ADFモデル・テスターを使用し、カスタム・ユーザー・インタフェースを構築する前にシミュレート済のエンド・ユーザーとの対話を使用してADFアプリケーション・モジュールをテストして診断します。

Oracle ADFモデル・テスターを使用すると、独自のカスタム・ユーザー・インタフェースを作成する前に、エンド・ユーザーとアプリケーション・モジュールのデータ・モデルとの対話をシミュレートできます。UIページを作成したも、Oracle ADFモデル・テスターは問題発生時の診断に役立ちます。Oracle ADFモデル・テスターで問題を再現して、問題がアプリケーションのビューまたはコントローラ・レイヤーにあるのか、あるいはビジネス・サービス・レイヤーのアプリケーション・モジュール自体にあるのかを確認できます。

Oracle ADFモデル・テスターの実行方法

アプリケーション・モジュールに追加したビュー・オブジェクトをテストするには、「アプリケーション」ウィンドウからアクセスできるOracle ADFモデル・テスターを使用します。「アプリケーション」ウィンドウからテスターを実行すると、デフォルトのアプリケーション・モジュール構成を使用してデータベースへの接続が行われます。

始める前に:

Oracle ADFモデル・テスターの知識があると役立ちます。詳細は、「Oracle ADFモデル・テスターを使用したビュー・オブジェクト・インスタンスのテスト」を参照してください。

テスターを実行する場合のデバッグ・ツールの使用方法を理解しておくと役に立つ場合があります。詳細は、「テストとデバッグのためのOracle ADFモデル・テスターの使用」を参照してください。

他のOracle ADF機能を使用して追加できる機能を理解しておくことも役立ちます。詳細は、「ビュー・インスタンスのテストの追加機能」を参照してください。

アプリケーション・モジュール構成を使用してビュー・オブジェクトをテストするには:

  1. 「アプリケーション」ウィンドウで、実行するアプリケーション・モジュールを右クリックし、「実行」を選択します。

    または、デバッグを有効にしたOracle ADFモデル・テスターでアプリケーションを実行する場合は、「デバッグ」を選択します。JDeveloperにより、「ログ」ウィンドウのデバッガ・プロセス・パネルおよび各種デバッガ・ウィンドウが開きます。たとえば、Oracle ADFモデル・テスターを使用してデバッグする場合、ステータス・メッセージと例外を表示し、ソース・コードをステップ・インおよびステップ・アウトし、ブレークポイントを管理できます。

    ADFビジネス・コンポーネントのデバッグに特有の診断メッセージを受信する方法の詳細は、「ADFビジネス・コンポーネント・デバッグ診断を有効化する方法」を参照してください。

  2. Oracle ADFモデル・テスターでビュー・オブジェクトを実行するには、データ・モデル・ツリーを開き、目的のビュー・オブジェクト・ノードをダブルクリックします。

    ビュー・オブジェクト・インスタンスはすでにテスト・セッションで実行されているように表示される場合があります。この場合、Oracle ADFモデル・テスターの右側のデータ・ビュー・ページには、すでにビュー・オブジェクト・インスタンスの問合せ結果が表示されています。Oracle ADFモデル・テスターでは、読取り専用ビュー・オブジェクトのデータ・ビュー・ページのフィールドは常に無効として表示されます。これは、このビュー・オブジェクトで表されるデータが編集できないためです。たとえば、図8-6では、ビュー・インスタンスProductsのデータがテスターに表示されています。「製品ID」「言語」「カテゴリ」などのフィールドは、属性を編集できないため、無効として表示されます。

    図8-6 Oracle ADFモデル・テスターでのデータ・モデルのテスト

    図8-6の説明が続きます
    「図8-6 Oracle ADFモデル・テスターでのデータ・モデルのテスト」の説明
  3. データ・モデル・ツリー内のノードを右クリックして、そのノードのポップアップ・メニューを表示します。たとえば、ビュー・オブジェクト・ノードでは、データ・モデル・ツリーからのビュー・オブジェクトの削除、およびその他のタスクの実行のため、必要に応じて問合せを再実行できます。
  4. タブのポップアップ・メニューを表示するには、図8-7で示すように、開いているデータ・ビューアのタブを右クリックします。たとえば、データ・ビューアを閉じたり、別のウィンドウで開くことができます。

    図8-7 Oracle ADFモデル・テスターのデータ・ビューアのタブのポップアップ・メニュー

    この図は周囲のテキストで説明しています

構成を使用したOracle ADFモデル・テスターの実行方法

アプリケーション・モジュールに追加したビュー・オブジェクトをテストするには、Oracle ADFモデル・テスターを使用し、特定の構成でテスターを実行します。選択する構成によって、テスターで使用されるデータベース接続が決まります。

始める前に:

Oracle ADFモデル・テスターの知識があると役立ちます。詳細は、「Oracle ADFモデル・テスターを使用したビュー・オブジェクト・インスタンスのテスト」を参照してください。

テスターを実行する場合のデバッグ・ツールの使用方法を理解しておくと役に立つ場合があります。詳細は、「テストとデバッグのためのOracle ADFモデル・テスターの使用」を参照してください。

他のOracle ADF機能を使用して追加できる機能を理解しておくことも役立ちます。詳細は、「ビュー・インスタンスのテストの追加機能」を参照してください。

特定のアプリケーション・モジュール構成を使用してビュー・オブジェクトをテストするには:

  1. 「アプリケーション」ウィンドウで、実行するアプリケーション・モジュールをダブルクリックします。
  2. 概要エディタで、「構成」ナビゲーション・タブをクリックします。
  3. 「構成」ページで、「デフォルト構成」ドロップダウン・リストから、Oracle ADFモデル・テスターの実行に使用するアプリケーション・モジュール構成を選択します。

    デフォルトでは、アプリケーション・モジュールには、AppModuleNameLocalおよびAppModuleNameSharedという名前のデフォルトの構成のみがあります。たとえば、図8-8では、データベースへの接続にBackOfficeAppModuleShared構成が選択されています。

    図8-8 アプリケーション・モジュールの概要エディタでの構成の選択

    図8-8の説明が続きます
    「図8-8 アプリケーション・モジュールの概要エディタでの構成の選択」の説明
  4. 選択した構成を右クリックして、「実行」を選択します。

    または、デバッグを有効にしたOracle ADFモデル・テスターでアプリケーションを実行する場合は、「デバッグ」を選択します。JDeveloperにより、「ログ」ウィンドウのデバッガ・プロセス・パネルおよび各種デバッガ・ウィンドウが開きます。たとえば、Oracle ADFモデル・テスターを使用してデバッグする場合、ステータス・メッセージと例外を表示し、ソース・コードをステップ・インおよびステップ・アウトし、ブレークポイントを管理できます。

    ADFビジネス・コンポーネントのデバッグに特有の診断メッセージを受信する方法の詳細は、「ADFビジネス・コンポーネント・デバッグ診断を有効化する方法」を参照してください。

言語メッセージ・バンドルおよびUIヒントのテスト方法

アプリケーションにおいて、リソース・メッセージ・バンドル内に代替言語を定義する場合、これらの言語を認識するようにOracle ADFモデル・テスターを構成できます。Oracle ADFモデル・テスターで「ロケール」メニューを表示し、利用可能な言語の中から選択できます。

Oracle ADFモデル・テスターのデフォルト言語を指定するには:

  1. メイン・メニューで、「ツール」「プリファレンス」を選択します。
  2. 「プリファレンス」ダイアログで、「ADFビジネス・コンポーネント」を開き、「テスター」を選択します。
  3. Oracle ADFモデル・テスター・ページで、リソース・メッセージ・バンドルを作成したロケールを「選択済」リストに追加します。

または、特定のアプリケーション・モジュール構成に対してADFビジネス・コンポーネントのランタイム構成プロパティを設定することによっても、デフォルト言語を構成できます。これらのランタイム・プロパティにより、Oracle ADFモデル・テスターでデフォルトとして表示される言語も決定されます。ランタイム構成のプロパティを設定するには、「アプリケーション」ウィンドウでアプリケーション・モジュールをダブルクリックして、概要エディタの「構成」ナビゲーション・タブを選択します。次に、概要エディタの「構成」ページで構成を選択し、構成のハイパーリンクをクリックします。アプリケーション・モジュール構成の概要エディタ(bc4j.xcfgファイル)で「プロパティ」タブを選択し、「プロパティの追加」をクリックして「プロパティの追加」ダイアログから次のプロパティを選択し、「OK」をクリックします。

  • jbo.default.country

  • jbo.default.language

次に、「プロパティ」リストで、国および言語の国コードを入力します。たとえば、イタリア語を指定するには、次の2つのプロパティに対してITおよびitと入力します。

  • jbo.default.country = IT

  • jbo.default.language = it

Oracle ADFモデル・テスターで言語メッセージ・バンドルをテストすることで、UIヒントの翻訳が正しく配置されているかどうかを検証できます。または、メッセージ・バンドルが特定の属性の日付書式を定義している場合は、ツールによって日付書式の変更(たとえば、04/12/2013から12/04/2013へ)を検証できます。

エンティティ・ベースのビュー・オブジェクトの対話的テスト方法

エンティティ・ベースのビュー・オブジェクトの対話的テストは、読取り専用ビュー・オブジェクトと同じ方法で行います。目的のビュー・オブジェクトのインスタンスをアプリケーション・モジュールのデータ・モデルに追加してから、Oracle ADFモデル・テスターを使用してこのアプリケーション・モジュールをテストします。

Oracle ADFモデル・テスターでは、アプリケーション・モジュールを簡単にテストおよびデバッグできるので、非常に便利です。表8-1に、エンティティ・ベースのビュー・オブジェクトを表示した場合にOracle ADFモデル・テスターのツールバー・ボタンで実行される操作の概要を示します。

表8-1 Oracle ADFモデル・テスターのツールバー・ボタン

ボタン 操作 用途
...行への移動アイコン

別の行に移動

Oracle ADFモデル・テスターで表示される現在の行を変更します。最初、前、次、または最後の行に移動します。

新しい行の挿入アイコン

新規行を挿入

新規の行を作成して挿入します。

「現在の行の削除」アイコン

現在の行を削除

現在の行を削除します。

「データベースへの変更を保存」アイコン

データベースへの変更を保存

ADFビジネス・コンポーネント・キャッシュに加えた変更をポストしてコミットします。

「前回の保存以降の変更をすべて取消」アイコン

前回の保存以降の変更をすべて取消し

ADFビジネス・コンポーネント・キャッシュで加えた変更を破棄して元の値に戻し、データベースにポストされたすべての変更をロールバックします。

「ビュー基準の指定」アイコン

ビュー基準の指定

「ビュー基準」ダイアログが表示されます。ここでビュー基準を作成して、マスター・ビュー・オブジェクト・インスタンスに適用できます。

「行の検証」アイコン

行の検証

すべてのエンティティ・オブジェクト・インスタンスに対して定義済の検証規則を適用し、現在の行を検証します。最低1つのフィールドが編集可能でないと、使用できません。

「バインド変数の編集」アイコン

バインド変数の編集

「バインド変数」ダイアログが表示され、ビュー・オブジェクト問合せで使用されるバインド・パラメータの値を入力できます。問合せ文のビュー・オブジェクト問合せでバインド・パラメータが使用されていないと、使用できません。

アプリケーション・モジュールに追加したエンティティ・ベースのビュー・オブジェクトをテストするには、「アプリケーション」ウィンドウからアクセスできるOracle ADFモデル・テスターを使用します。

始める前に:

Oracle ADFモデル・テスターの知識があると役立ちます。「Oracle ADFモデル・テスターを使用したビュー・オブジェクト・インスタンスのテスト」を参照してください。

他のOracle ADF機能を使用して追加できる機能を理解しておくことも役立ちます。「ビュー・インスタンスのテストの追加機能」を参照してください。

アプリケーション・モジュール構成を使用してエンティティ・ベースのビュー・オブジェクトをテストするには:

  1. 「アプリケーション」ウィンドウで、テストするアプリケーション・モジュールを右クリックし、「実行」を選択します。
  2. Oracle ADFモデル・テスターでデータ・モデル・ツリーを開き、目的のエンティティ・ベースのビュー・オブジェクト・ノードをダブルクリックします。

    読取り専用ビュー・オブジェクトと異なり、データ・ビュー・ページに表示されるフィールドは、そのビュー・オブジェクトで表されるデータを編集できるため、有効として表示されます。

  3. 個々の値を更新し、入力したデータの検証チェックを実行するには、編集可能なフィールドを使用します。

    参照されるエンティティを持つビュー・インスタンスの場合は、外部キー値を変更して、参照部分の変更を確認できます。

  4. 行の移動、作成、削除、現在の行の検証など、行レベルの操作を実行するには、ツールバー・ボタンを使用します。

    エンド・ユーザーによるデータ・ビュー・ページ操作のシミュレーションの詳細は、「Oracle ADFモデル・テスターでのエンド・ユーザーによる対話のシミュレーション方法」を参照してください。

Oracle ADFモデル・テスターを更新してプロジェクトの変更を表示する方法

通常、データ・モデル・プロジェクトに対して行う変更は、Oracle ADFモデル・テスターを実行しても自動的に取得されません。ただし、表示されたデータ・モデルとデータ・モデル・プロジェクトの同期を取る必要があるときはいつでも、Oracle ADFモデル・テスターがデータ・モデル・プロジェクトからメタデータをリロードできます。このオプションを使用すると、Oracle ADFモデル・テスターを終了してプロジェクトを編集しOracle ADFモデル・テスターを再実行しなくても、最新の変更を表示できます。

「アプリケーションのリロード」オプションを使用すると、特にOracle ADFモデル・テスターとJDeveloperを繰り返し切り替えて作業する場合に時間を節約できます。たとえば、Oracle ADFモデル・テスターの実行中に、新しいビュー・インスタンスを使用してデータ・モデルを変更する必要が生じたり、ビュー・インスタンスにLOV属性定義が足りないことが判明することがあります。JDeveloperに戻り、ビジネス・コンポーネントの概要エディタを使用して変更操作を行い、データ・モデルのメタデータを変更します。その後、プロジェクトを再コンパイルした後(必須のステップ)、Oracle ADFモデル・テスターに戻って、プロジェクトのクラス・パスから更新済のメタデータをリロードできます。

始める前に:

Oracle ADFモデル・テスターの知識があると役立ちます。詳細は、「Oracle ADFモデル・テスターを使用したビュー・オブジェクト・インスタンスのテスト」を参照してください。

他のOracle ADF機能を使用して追加できる機能を理解しておくことも役立ちます。詳細は、「ビュー・インスタンスのテストの追加機能」を参照してください。

稼働中のOracle ADFモデル・テスターにデータ・モデルのメタデータを再ロードするには:

  1. 「アプリケーション」ウィンドウで、アプリケーション・モジュールを右クリックし、「実行」を選択します。
  2. Oracle ADFモデル・テスターで、データ・モデルをテストして、必要な変更を判別します。Oracle ADFモデル・テスターは終了しないでください。
  3. JDeveloperで、目的の変更を行い、データ・モデル・プロジェクトを再コンパイルします(たとえば、「アプリケーション」ウィンドウでデータ・モデル・プロジェクトを右クリックし、「メイク」を選択して再コンパイル・ステップを完了します。)

    メタデータに対して行う変更とプロジェクトのコンパイルに関連性はありませんが、メタデータをクラス・パスにコピーし、Oracle ADFモデル・テスターでリロードできるようにするには、コンパイル・ステップを実行する必要があります。

  4. ADFモデル・テスターに戻り、データ・モデル・ツリーの上にある「アプリケーション・メタデータのリロード」ボタンをクリックします。Oracle ADFモデル・テスターの開いているウィンドウがすべて閉じます。

    また、Oracle ADFモデル・テスターの「ファイル」メニューから、「アプリケーションのリロード」を選択してもかまいません。

  5. 目的のウィンドウを再度開き、行った変更を表示します。

Oracle ADFモデル・テスター使用時の処理

Oracle ADFモデル・テスターを起動すると、JDeveloperによってこのツールが別プロセスで開始され、Oracle ADFモデル・テスターが表示されます。ダイアログの左側のツリーには、アプリケーション・モジュールのデータ・モデルのすべてのビュー・オブジェクト・インスタンスが表示されます。目的のビュー・オブジェクト・インスタンスをダブルクリックすると、Oracle ADFモデル・テスターでデータ・ビュー・ページが表示され、問合せ結果をインスペクトできます。たとえば、図8-9は、展開されたツリーでビュー・インスタンスProductsをダブルクリックし、右側のデータ・ビュー・ページにこのビュー・インスタンスのデータが表示された様子を示しています。

データは編集できないため、表示する読取り専用のビュー・オブジェクトすべてに対して、データ・ビュー・ページは無効になっています。ただし、読取り専用のビュー・オブジェクトの場合でも、ツールはいくつかの有用な機能を備えています。

  • 「ラベル・テキスト」ヒントに基づいたUIヒント、およびフォーマット・マスクが正しく定義されているかどうかを検証できます。

  • ツールバー・ボタンを使用してデータのスクロールもできます。

  • Query-By-Example基準を入力して、検査対象のデータのある特定の行を検索できます。ツールバーの「ビュー基準の指定」ボタンをクリックすると、「ビュー基準」ダイアログに使用可能なQuery-by-Example基準のリストが表示されます。

    たとえば、図8-9に示すように、FindByProductNameCriteriaなどのビュー基準を選択し、ProductName属性にP%などの問合せ基準を入力して「検索」をクリックすると、検索対象を文字Pで始まる名前の製品のみに絞り込むことができます。

「エンティティ・ベースのビュー・オブジェクトの対話的テスト方法」で説明しているように、行の挿入、更新および削除をシミュレートできるエンティティ・ベースのビュー・オブジェクトを作成する場合は、Oracle ADFモデル・テスターをより便利に使用できます。

図8-9 組込みQuery-By-Example機能

図8-9の説明が続きます
「図8-9 組込みQuery-By-Example機能」の説明

Oracle ADFモデル・テスターでのエンド・ユーザーによる対話のシミュレーション方法

Oracle ADFモデル・テスターを起動すると、アプリケーション・モジュールのデータ・モデルで定義されているビュー・オブジェクト・インスタンスの階層が左側のツリーに表示されます。データ・モデルにマスター/ディテールのビュー・インスタンス関係が定義されている場合、ツリーには親ノードと子コードとして関係が表示されます。マスター/ディテールのビュー・インスタンス間のノードは、マスターで現在の行が変更されたときにマスター/ディテールをアクティブに調整するビュー・リンク・インスタンスを示します。たとえば、図8-10では、ツリーが開かれ、マスター・ビュー・インスタンスProductsとディテール・ビュー・インスタンスWarehouseStockLevelsのマスター/ディテール関係が示されています。選択されているノード、ProductsToWarehouseStockLevels1は、マスター/ディテール関係が定義されているビュー・リンク・インスタンスです。

図8-10 Oracle ADFモデル・テスターのアプリケーション・モジュールのデータ・モデル

この図は周囲のテキストで説明しています

ビュー・リンク・インスタンスをダブルクリックすると、マスター・オブジェクトが実行され、データ・ビュー・ページにマスター/ディテール・データが表示されます。たとえば、図8-11では、ツリーのProductsToWarehouseStockLevels1ビュー・リンク・インスタンスをダブルクリックすると、データ・ビュー・ページ上部のProductsマスター・ビュー・インスタンスと、データ・ビュー・ページ下部のWarehouseStockLevelsビュー・インスタンスが実行されます。ビュー・オブジェクト・ノード上に表示される追加ポップアップ・メニュー項目では、データ・モデル・パネルからのビュー・オブジェクトの削除、およびその他のタスクの実行のため、必要に応じて問合せを再実行できます。

マスター/ディテール・データ・ビュー・ページでは、問合せ結果をスクロールできます。また、エンティティ・ベースのビュー・オブジェクトのインスタンスは完全に編集可能なため、読取り専用ビュー・オブジェクトの読取り専用のデータを表示している無効な UIコントロールを表示するかわりに、データ・ビュー・ページには編集可能なフィールドが表示されます。作成、挿入、更新、検証、コミットおよびロールバックを自由に試すことができます。

図8-11 Oracle ADFモデル・テスターのマスター/ディテール・データ・ビュー・ページ

この図は周囲のテキストで説明しています

たとえば、複数のデータ・ビュー・ページを同時に開いて、マスター/ディティール階層の複数レベルを表示できます。「連結解除」ポップアップ・メニュー項目を使用して、任意のタブを別のウィンドウで開き、複数のビュー・オブジェクトのデータを同時に視覚化します。

マスター/ディテール・データ・ビュー・ページを使用して、アプリケーションの様々な機能領域をテストできます。

マスター/ディテール調整のテスト

Oracle ADFモデル・テスターのツールバーのナビゲーション・ボタンをクリックすると、現在のマスター・ビュー・オブジェクトの行が正しく調整されているかどうかを確認できます。たとえば、図8-11は、製品と倉庫のマスター/ディテール階層を示しています。マスター・パネルの次の行ボタンをクリックすると、(製品IDで識別された)次の製品がマスター・パネルに表示され、ディテール・パネルが更新されてこの製品を在庫として持つ倉庫と数量のリストが表示されます。

UIヒントのテスト

エンティティ・ベースのビュー・オブジェクトの属性は、基礎となるエンティティ・オブジェクト属性からUIヒントを継承します。データ・ビュー・ページに表示されるプロンプトを見ると、属性ごとにわかりやすいラベル・テキストUIヒントが正しく定義されているかどうかを確認できます。エンティティ・オブジェクトにヒントを設定する方法の詳細は、「ビュー・オブジェクトのUIヒントの定義」を参照してください。

ビジネス・ドメイン・レイヤーの検証のテスト

定義した検証規則に応じて、無効な値を入力して検証例外のトリガーおよび検証を試行できます。たとえば、レンジ検証規則を定義した場合、レンジ外の値を入力し、次のようなエラーが表示されるのを確認します。

(oracle.jbo.AttrSetValException) Valid product codes are between 100 and 999

ツールバーで「ロールバック」ボタンをクリックし、データを以前の状態に戻してください。

エンティティ・オブジェクトの慣用名を参照するビュー・オブジェクトのテスト

データをスクロールするか、Oracle ADFモデル・テスターのツールバーにある「ビュー基準の指定」ボタンを使用して検索すると、エンティティ・ベースのビュー・オブジェクトの問合せのWHERE句を正しく変更し、外部結合を使用するようにしたかどうかを検証できます。想定どおりに行が表示されるはずです。

マスター・ビュー・オブジェクトの主キー属性の変更も試行できます。これにより、対応する参照情報が新しい主キー値を反映するように自動的に更新されているかどうかを検証できます。

ビュー・オブジェクト・レベルで定義したUIヒントによって、通常は基礎となるエンティティ・オブジェクトから継承されるUIヒントがオーバーライドされたかどうかは、Oracle ADFモデル・テスターを使用して検証します。複数の属性が同じラベル・テキストを共有していることに気付いた場合は、ビュー・オブジェクト・レベルで目的の属性に対するUIヒントを編集できます。たとえば、「ラベル・テキスト」ヒントを、RegisteredDate 属性は「Member Since」ProvisionedFlag属性は「Provisioned?」に設定します。

行の作成およびデフォルト値の生成のテスト

エンティティ・ベースのビュー・オブジェクトを表示する際に、ビュー・オブジェクト・インスタンスに対してOracle ADFモデル・テスターのツールバーの行の作成ボタンをクリックすると、新しい空白の行が作成されます。宣言的なデフォルト値があるフィールドの場合、その値が空白行に表示されます。DBSequence値の属性を使用すると、新しい行に一時値が表示されます。すべての必須フィールドに入力した後、「コミット」ボタンをクリックしてトランザクションをコミットします。コミットが成功した後、トリガーによって割り当てられた実際の主キーがフィールドに表示されます。

新しいディテール行の外部キーが正しいかどうかのテスト

Oracle ADFモデル・テスターのツールバーの行の作成をクリックして、既存のディテール・エンティティ・ベースのビュー・オブジェクト・インスタンスに新しい行を追加しようとすると、ビュー・リンクによって、新しい行の外部キー属性値が現在のマスター・ビュー・インスタンス行の値に自動的に設定されることがわかります。

Oracle ADFモデル・テスターでのマルチ・ユーザー・シナリオのテスト方法

ビュー・オブジェクトとエンティティ・オブジェクトが実行時に連携する場合、マルチユーザー環境でアプリケーションを実行すると2つの例外が発生する可能性があります。これらの例外に備えて、Oracle ADFモデル・テスターを使用して、テスト目的のマルチ・ユーザー環境をシミュレートできます。たとえば、アプリケーションにビュー・オブジェクト問合せの編集フォームが表示される場合に、2人のユーザーがフォームで同じ属性を編集しようとすると、どのような動作が予想されるでしょうか。

予想される動作を理解するために、アプリケーション・モジュール上でOracle ADFモデル・テスターの2つのインスタンスを開き、同一のビュー・オブジェクト属性を編集する2人のユーザーをシミュレートします。2つのインスタンスを開いたまま、どのようにマルチユーザー例外が発生するかを表す次の2つのテストを実行します。

  • Oracle ADFモデル・テスターの1つのインスタンスで、既存のビュー・オブジェクトの属性を変更し、このフィールドから次に進みます。次に、テスターのもう1つのインスタンスで、同じビュー・オブジェクトの属性をなんらかの形で変更してみます。2人目のユーザーには、oracle.jbo.AlreadyLockedExceptionが発生します。

    ここで、Oracle ADFモデル・テスターの「接続」ダイアログの「プロパティ」ページで、jbo.locking.modeの値をpessimisticに変更し、テストを繰り返して試行します(デフォルト・モードはoptimisticに設定されています)。エラーが発生するのは、2人目のユーザーが変更をコミットした後ではなく、値を変更した直後であることがわかります。

  • Oracle ADFモデル・テスターの1つのインスタンスで、既存のビュー・オブジェクトの属性を変更し、このフィールドから次に進みます。次に、テスターのもう1つのインスタンスで、同じビュー・オブジェクトの属性を変更せずに取得してみます。最初のウィンドウに戻り、変更をコミットします。2人目のユーザーが同じ属性を変更しようとすると、oracle.jbo.RowInconsistentExceptionが発生します。これは、2人目のユーザーが行をエンティティ・キャッシュに取得した後に、行が別のユーザーによって変更されてコミットされたためです。

テスターを実行する前の構成オプションのカスタマイズ方法

アプリケーション・モジュールの概要エディタを使用して、事前定義済の構成を選択し、実行時構成プロパティの名前付きセットを使用してツールを実行できます。概要エディタの「構成」ページでは、アプリケーション・モジュール構成(bc4j.xcfgファイルで定義)の概要エディタを開き、テスターを実行する前に構成のプロパティを指定することもできます。

アプリケーション・モジュール構成の概要エディタを表示するには、「アプリケーション」ウィンドウでアプリケーション・モジュールをダブルクリックして、概要エディタの「構成」ナビゲーション・タブを選択します。次に、概要エディタの「構成」ページで構成を選択し、構成のハイパーリンクをクリックします。アプリケーション・モジュール構成の概要エディタで「プロパティ」タブを選択し、「プロパティの追加」をクリックして「プロパティの追加」ダイアログで目的のプロパティを選択し、「OK」をクリックします。

たとえば、構成を編集し「プロパティ」タブを選択して、次の2つのプロパティを追加して目的の国コード(この場合はイタリアを表すIT)を設定することにより、UIヒントのデフォルト言語を変更できます。

  • jbo.default.country = IT

  • jbo.default.language = it

ADFビジネス・コンポーネント・デバッグ診断を有効化する方法

oracle.jboログ出力に診断ロギングを構成している場合、Oracle ADFモデル・テスターを起動すると、JDeveloperによりADFビジネス・コンポーネントのデバッグ診断メッセージがJDeveloperの「ログ」ウィンドウにリダイレクトされます。図8-12に、ADFビジネス・コンポーネントのデバッグ診断が有効になるようにFINESTに設定されたoracle.jboログ出力を示します。

図8-12 ADFビジネス・コンポーネントのデバッグ用のログ出力の構成

この図は周囲のテキストで説明しています

oracle.jboログ出力は、統合WebLogic Serverでアプリケーションを実行する前、またはアプリケーションの実行中に構成できます。ロギングは、サーバーを再起動しなくても開始されます。診断メッセージのログ出力を得るためにアプリケーションをデバッグ・モードで実行する必要はありません。

oracle.jboのログ出力が構成された状態で、次にOracle ADFモデル・テスターを実行してビュー・オブジェクトをダブルクリックすると、次の例に示すように、「ログ」ウィンドウに詳細な診断出力が表示されます。oracle.jboログ出力にログ・レベルFINESTを構成すると、ADFビジネス・コンポーネント・フレームワークのコンポーネントによってアプリケーションに実行されるすべての内容を表示できます。

  :
[355] Oracle SQLBuilder: Registered driver: oracle.jdbc.OracleDriver
[356] Creating a new pool resource
[357] **** DBTransactionImpl establishNewConnection
[358] Successfully logged in
[359] JDBCDriverVersion: xx.xx.x.x-Production
[360] DatabaseProductName: Oracle
[361] DBTransactionImpl initTransaction
[362] Replacing: null with: StoreServiceAM_AddressesPageDef
[363] Replacing: null with: StoreServiceAM_MostPopularProductsByCategoriesPageDef
...
[537] Orders ViewRowSetImpl.execute caused params to be "un"changed
[538] Column count: 41
[539] ViewObject: Orders Created new QUERY statement
[540] Orders>#q computed SQLStmtBufLen: 952, actual=865, storing=895
[541] SELECT OrderEO.ORDER_ID, OrderEO.ORDER_DATE, OrderEO.ORDER_SHIPPED_DATE,
       FROM ORDERS OrderEO ORDER BY OrderEO.ORDER_DATE desc
[542] Bind params for ViewObject: Orders

後方互換性の目的で、データ・モデル・プロジェクトに対し従来のようにJavaシステム・プロパティjbo.debugoutput=consoleを使用して、ADFビジネス・コンポーネント・デバッグ診断を有効化できます。このプロパティを設定するには、データ・モデル・プロジェクトの「プロジェクト・プロパティ」ダイアログの実行/デバッグ/プロファイル・ページを開きます。「編集」をクリックして選択した実行構成を編集し、ページ内の「Javaオプション」フィールドに-Djbo.debugoutput=consoleを追加します。このプロパティの他の有効な値は、silent(指定されていない場合、デフォルト)およびfileです。fileオプションを選択すると、診断はsystem tempディレクトリに書き込まれます。

-Djbo.debugoutputシステム・プロパティの他の有効な値は、silent(指定されていない場合、デフォルト)およびfileです。fileオプションを入力すると、診断はシステムのtempディレクトリに書き込まれます。

実行時のビュー・オブジェクトとエンティティ・オブジェクトの連携処理

ビュー・オブジェクトとエンティティ・オブジェクトにより、すべてのエンタープライズ・アプリケーション開発者が実行する必要のある次の2つの重要なジョブが単独で簡略化されます。

  • SQL問合せ結果の操作

  • データベース表内の行の変更および検証

エンティティ・ベースのビュー・オブジェクトは、エンド・ユーザーが表示または変更できるようにする必要のあるデータを任意に選択して問い合せることができます。エンド・ユーザーによる変更が可能なデータは、再使用可能なビジネス・ドメイン・レイヤーによって検証および保存されます。開発者が指定するのは、開発者のみが把握できる重要事項です。

  • ビジネス・ドメイン・レイヤーにどのビジネス・ロジックを適用するかの決定

  • 画面に表示する必要のあるデータを記述する問合せの決定

これらにより、開発者のアプリケーションが独自のものになります。実装の残りの詳細部分は、エンティティ・ベースのビュー・オブジェクトに組み込まれた機能によって処理されます。

ノート:

行キーおよびエンティティ・キャッシュがトランザクションで果す役割について理解することは、エンティティ・ベースのビュー・オブジェクトの本質を明確にするために役立つ重要な概念です。これら2つの概念は、「ビュー・オブジェクトのデフォルト行セットを使用した操作のViewObjectインタフェース・メソッド」で説明します。

ビュー・オブジェクトによる問合せ実行後の処理

エンティティ・ベースのビュー・オブジェクトのインスタンスをアプリケーション・モジュールのデータ・モデルに追加した後、問合せの実行時に行われる処理を確認できます。読取り専用ビュー・オブジェクトの場合と同様、エンティティ・ベースのビュー・オブジェクトが標準のJDBC (Java Database Connectivity) APIを使用してデータベースにSQL問合せを直接送信し、データベースが結果セットを生成します。ただし、読取り専用ビュー・オブジェクトの場合とは異なり、エンティティ・ベースのビュー・オブジェクトは、データベースの結果セットの各行を取得するときに、関連付けられているエンティティ・オブジェクトの慣用名に基づいて行属性を分割します。この分割の際、各ビュー・オブジェクトのエンティティ・オブジェクトの慣用名に適切なタイプのエンティティ・オブジェクト行が作成され、問合せによって取得された関連属性がこれらのエンティティ行に移入され、このようなエンティティ行がそれぞれ個別のエンティティ・キャッシュに格納されます。これにより、データの複製コピーを格納するかわりに、ビュー行は、これを構成するエンティティ行部分を指し示すだけでになります。

図8-13は、エンティティ・キャッシュにより、2つのエンティティ・ベース・ビュー・オブジェクトの結果セット属性がどのように分割されるかを示しています。この例では、データベース結果セットで強調表示された行は、主キー112Orderエンティティ行と、主キー301CustomerInfoエンティティ行に分割されています。

「エンティティ・キャッシュがトランザクションで果す役割」で説明するように、findByPrimaryKey()を使用してキャッシュに取り込んだエンティティ行には、エンティティ・オブジェクトのすべての属性が含まれています。一方、エンティティ・ベースのビュー・オブジェクトの問合せ結果の行を分割して作成されたエンティティ行には、問合せ結果に表れる属性の値のみが含まれます。これには完全な属性セットは含まれていません。このようにエンティティ行が部分的に移入されることにより、実行時のパフォーマンスが大幅に最適化されます。

一般的なエンタープライズ・アプリケーションで変更される行と比較して、取得される行の比率が非常に高くなるため、表示する必要がある属性のみをメモリーに読み込むことにより、常にすべての属性をメモリーに読み込む場合よりもメモリーを節約できます。

図8-13 エンティティ・キャッシュのエンティティ行に分割されるビュー行

例8-13の説明が続きます
「図8-13 エンティティ・キャッシュのエンティティ行に分割されるビュー行」の説明

このような方法で問合せ結果のデータを基礎となるエンティティ行の構成要素部分に分割すると、現在のトランザクションが変更された場合、問い合せた結果のデータを含むすべての行で整合している結果が表示されるという、重要な利点が得られます。つまり、あるビュー・オブジェクトで顧客301PaymentType属性を変更できる場合、顧客301PaymentType属性を表示する任意のエンティティ・ベースのビュー・オブジェクトのすべての行が即座に更新され、変更が反映されます。顧客301に関連付けられたデータがCustomerInfoエンティティ・キャッシュで主キー301を持つエンティティ行に格納されるのは1回のみであるため、オーダーのPaymentType属性を問い合せたビュー行はどれも、この単一のエンティティ行を指し示すことになります。

このような実装の詳細は、ビュー・オブジェクトの行セット内の行を操作するクライアントに対しては完全に非表示にされます。クライアントは、ビュー行を操作して属性を取得して設定する際、これらの属性がその背後でどのようにエンティティ行に関連付けられているかには気付きません。

ビュー行属性変更後の実行時の処理

ユーザーがビュー行属性を変更しようとすると、基礎となるエンティティ行に応じてこのビュー行属性の変更を自動的に調整する一連のステップが実行されます。これらのステップにより、エンティティ・マップ属性で定義された検証規則は、値が変更される前にトリガーされます。

図8-14は、ユーザーがエンティティ・マップされた属性を更新しようとするときに実行時に発生する基本的なステップを示しています。この例では、変更される属性Statusが、検証規則が定義されているエンティティ・オブジェクトの慣用名にマップされています。

  1. ユーザーがStatus属性の値をShipに設定しようとします。

  2. StatusOrderエンティティ・オブジェクトの慣用名にマップされた属性であるため、ビュー行は、Orderエンティティ・キャッシュ内で主キー112を持つ、基礎となるエンティティ行に設定されている属性を委譲します。

  3. Orderエンティティ・オブジェクトのStatus属性に対する属性レベルの検証規則が評価され、規則が失敗した場合は変更が失敗します。

    Status属性の検証規則によってShipDate属性がプログラム的に参照されるとします(たとえば、Orderは発注日と同日に出荷済にはできないというビジネス・ルールを適用する必要がある場合など)。ShipDateは、問合せによって取得されたOrder属性ではないため、Orderエンティティ・キャッシュ内に部分的に移入されたエンティティ行にはありません。

  4. ビジネス・ルールでエンティティ・オブジェクトのすべての属性を常に参照可能にするため、エンティティ・オブジェクトはこの状況を検出し、主キーによって変更されるエンティティ行についてOrder エンティティ・オブジェクト属性のセット全体を失敗にします(主キーはビュー・オブジェクトに適用される各エンティティ・オブジェクトの慣用名に表示されます)。

  5. 属性レベルの検証がすべて成功した後、エンティティ・オブジェクトでは、最初の属性の変更を許可する前にORDERS表でこの行にロックをかけます。

  6. この行をロックできた場合、行内のStatus属性の設定が成功し、エンティティ行でこの値が変更されます。

ノート:

jbo.locking.mode構成プロパティは、行のロック方法を制御します。デフォルト値はoptimisticです。通常、Fusion Webアプリケーションでは、このデフォルト設定のoptimisticを使用するため、トランザクションのコミット時まで行はロックされません。pessimisticロック・モードの場合、エンティティ・キャッシュで行に対する変更を許可する前に行のロックを可能にする必要があります。

図8-14 エンティティに委譲されるビュー行属性の更新

例8-14の説明が続きます
「図8-14 エンティティに委譲されるビュー行属性の更新」の説明
外部キー属性変更後の実行時の処理

ユーザーが外部キーの属性を変更しようとすると、基礎となるエンティティ行に応じてこのビュー行属性の変更を自動的に調整する一連のステップが実行されます。これらのステップにより、外部キーのエンティティ・マップ属性で定義された検証規則は、値が変更される前にトリガーされます。また、変更された外部キー属性のビュー行に、すべての参照されたエンティティ・オブジェクトの正しい属性が反映されます。

図8-15は、ユーザーが外部キーのエンティティ・マップ属性を更新しようとするときに実行時に発生する基本的なステップを示しています。この例では、変更される属性CustomerInfoIdは、エンティティ・オブジェクトの慣用名Orderにマップされており、ここでこの属性は別のエンティティ・オブジェクトであるCustomerInfoと関連付けられます。

  1. ユーザーがCustomerInfoId属性の値を300に設定しようとします。

  2. CustomerInfoIdOrderエンティティ・オブジェクトの慣用名にマップされた属性であるため、ビュー行は、Orderエンティティ・キャッシュ内で主キー112を持つ、基礎となるエンティティ行に設定されている属性を委譲します。

  3. Orderエンティティ・オブジェクトのCustomerInfoId属性に対する属性レベルの検証規則が評価され、規則が失敗した場合は変更が失敗します。

  4. この行はすでにロックされているため、行内のCustomerInfoId属性の設定が成功し、エンティティ行でこの値が変更されます。

  5. Orderエンティティ・オブジェクトの慣用名のCustomerInfoId属性は、CustomerInfoエンティティ・オブジェクトに関連付けられているため、外部キー値をこのように変更すると、ビュー行で、顧客301の現在のエンティティ行部分が、新しいCustomerInfoId = 300に対応するエンティティ行に置き換えられます。これにより、オーダー112のビュー行が300のエンティティ行を指し示すよう効率的に変更できるため、ビュー行のPaymentTypeの値が更新され、この新しく割り当てられた顧客の参照情報が正しく反映されます。

図8-15 外部キーの更新後に新しいエンティティを指し示すビュー行

例8-15の説明が続きます
「図8-15 外部キーの更新後に新しいエンティティを指し示すビュー行」の説明
トランザクションのコミット後の実行時の処理

変更に問題がなく、トランザクションをコミットするとします。図8-16に示すとおり、次の2つの基本ステップがあります。

  1. Transactionオブジェクトにより、保留中の変更リスト内の無効なエンティティ行が検証されます。

  2. 保留中の変更リスト内のエンティティ行がデータベースに保存されます。

この図は、1つの変更済エンティティ・オブジェクトの検証処理が他のエンティティ・オブジェクトに対する変更にプログラム的に影響する前に行う、ステップ1のループを示します。保留中の変更リスト上で無効なエンティティのリストが処理された後、リストにまだエンティティが残されている場合、トランザクションで別のパスが実行されます。リストのパススルーは最大10回行われます。この時点でまだ無効なエンティティ行がある場合は通常、ビジネス・ロジックにエラーがあり、このビジネス・ロジックを調査する必要があるため、例外がスローされます。

図8-16 トランザクションのコミット時に行われる無効なエンティティの検証とエンティティの保存

例8-16の説明が続きます
「図8-16 トランザクションのコミット時に行われる無効なエンティティの検証とエンティティの保存」の説明
ビュー・オブジェクトによるデータ再問合せ後の実行時の処理

ビュー・オブジェクトの問合せを再実行する場合、デフォルトでは、最新の結果セットを読み込むための準備中、現在の行セット内のビュー行は無視されます。ただし、このビュー・オブジェクト操作はエンティティ・キャッシュには直接影響しません。この場合、ビュー・オブジェクトがデータベースに対してSQLを送信することによってプロセスが再開され、データベースの結果セット行が取得され、エンティティ行部分に分割されます。

ノート:

通常、ビュー・オブジェクトでデータの問合せを再実行する場合、この操作では最新のデータベース情報を取得します。かわりにビュー・オブジェクトの問合せ対象をキャッシュ内の既存のエンティティ行のみに制限する場合や、すでにビュー・オブジェクトの行セット内にある既存の行に制限して、データベースのラウンドトリップを回避する場合は、「行セットのメモリー内でのソート処理とフィルタ処理の実行」を参照してください。

問合せの再実行時の変更なしの属性の処理

問合せの再実行時におけるこのエンティティ行分割プロセスの一環として、エンティティ行の属性が変更されていない場合、エンティティ・キャッシュ内の値が更新され、新しい問合せ結果の値が反映されます。

問合せの再実行時の変更されたの属性の処理

一方、現在のトランザクションでエンティティ行属性の値が変更されている場合、問合せ再実行時のエンティティ行の分割プロセスでは、値はリフレッシュされません。現在のトランザクションでコミットされない変更はそのまま残されるため、エンド・ユーザーの論理作業ユニットは保持されます。任意のエンティティ属性値の場合と同様、これらの保留中の変更は、変更済エンティティ行を参照する任意のエンティティ・ベースのビュー・オブジェクト行に継続して表示されます。

ノート:

エンド・ユーザーによる行の挿入および削除はエンティティ・キャッシュでも管理されるため、問合せの再実行時に、新規行を表示して削除済の行をスキップできます。新しい行の動作の詳細は、「同じエンティティに基づくビュー・オブジェクトでの新しい行の一貫性の保持」を参照してください。

たとえば、図8-17は、ユーザーがOrdersビュー・オブジェクト・インスタンスを使用する別のページにドリルダウンし、オーダー112に関する詳細を取得するシナリオを示しており、これは現在のトランザクションの保留中の変更のコンテキストで発生します。このビュー・オブジェクトには、プライマリOrdersの慣用名と、CustomerInfoの参照の慣用名の、2つのエンティティ・オブジェクトの慣用名があります。問合せ結果がエンティティ行に分割されると、前のOrderInfoビュー行で変更されたものと同じOrderエンティティ行を指し示すことになります。つまり、エンド・ユーザーには保留中の変更が正しく表示され、オーダーはこのトランザクションのsking に割り当てられています。

図8-17 エンティティ・キャッシュにマージされる、個別ビュー・オブジェクトのエンティティ属性セット

この図は周囲のテキストで説明しています
問合せの再実行時の属性のサブセットのオーバーラップの処理

2つの異なるビュー・オブジェクトが、参照情報の2つの異なるサブセットを取得でき、属性の一致するセットの有無にかかわらず、結果がマージされます。たとえば、図8-17もこの状況を示しており、Ordersビュー・オブジェクトはユーザーのEmailを問い合せていますが、OrderInfoビュー・オブジェクトはユーザーのPaymentOptionを問い合せています。この図は、実行時に行われる処理を示しており、取得した行を分割する際に、すでにキャッシュ内にある部分的に移入されたエンティティ行とは異なる属性セットがエンティティ行部分に含まれる場合、属性はマージされます。その結果、キャッシュ内の部分的に移入されたエンティティ行に、オーバーラップするユーザー属性のサブセットが統合されます。一方、キャッシュ内になかったjchen(ユーザー302)の場合、新しいエンティティ行にはEmail属性のみが含まれ、PaymentOptionは含まれません。

ビュー・オブジェクトの実行時パフォーマンスの最適化に関する必知事項

ビュー・オブジェクトには、SQLの実行方法とデータベースからデータをフェッチする方法を制御するチューニング・パラメータが用意されています。これらのチューニング・パラメータは、ビュー・オブジェクトの実行時パフォーマンスで重要な役割を果たします。アプリケーションでフェッチ・オプションが正常にチューニングされないと、ビュー・オブジェクトが必要以上の量のデータをフェッチし、データベースへのラウンドトリップの回数が非常に増える場合があります。

表8-2に示すように、概要エディタの「一般」ページの「チューニング」セクションでは、フェッチ・オプションを設定できます。

表8-2 ビュー・オブジェクトのパフォーマンスをチューニングするためのパラメータ

フェッチをチューニングするパラメータ 用途

フェッチ・モード

デフォルトのフェッチ・オプションは「すべての行」オプションで、「必要に応じて」(FetchMode="FETCH_AS_NEEDED")、または「一度にすべて」(FetchMode="FETCH_ALL")のどちらのオプションが適切かに応じて取得されます。「必要に応じて」オプションでは、ビュー・オブジェクトでのexecuteQuery()操作において、まず表示の最初のページを埋めるために必要な数の行のみが取得されます(この行数は、ビュー・オブジェクトの範囲サイズに基づいて設定されます)。

フェッチ・サイズ

「次の単位で」フィールドでは、「フェッチ・モード」オプションと連携して、データベースから一度にフェッチされるレコード数(ビュー・オブジェクトXMLのFetchSize)を制御します。デフォルト値は1です(1行のみがフェッチされる場合を除き、パフォーマンスが低下します)。推奨構成として、この値をn+3に設定することをお薦めします。nはユーザー・インタフェースに表示される行数です。このパラメータがメモリー要件にどのような影響を及ぼすかの詳細は、「一度に1行のフェッチが適切かどうかの検討」を参照してください。

最大フェッチ・サイズ

ビュー・オブジェクトのデフォルトの最大フェッチ・サイズは-1で、ビュー・オブジェクトでフェッチできる行数に制限がないことを示します。結果セットにn行のデータしか含まれない場合は、「行番号までのみ」のオプションを選択して、nに設定してください。開発者は、setMaxFetchSize(n)をコールしてプログラム的に設定することも、ビュー・オブジェクトXMLにパラメータMaxFetchSizeを手動で追加することもできます。

WHERE句が単一の行を取得すると予想されるビュー・オブジェクトの場合は、オプションを「最大で1行」に設定します。このオプションを指定すると、ビュー・オブジェクトはユーザーがそれ以上の行を期待していないことを認識し、さらに行がある場合に通常行うテストをスキップします。

前述のように、最大フェッチ・サイズを0に設定すると、ビュー・オブジェクトは挿入専用になります。この場合は、選択問合せは発行されないため、行はフェッチされません。

アプリケーションのすべてのビュー・オブジェクト問合せに対してグローバルなしきい値を指定する必要がある場合は、adf-config.xmlファイルで「行フェッチ制限」プロパティを設定できます。このプロパティを設定することで、個別の問合せ操作に対して「最大フェッチ・サイズ」の変更を行う必要がなくなります。個別のビュー・オブジェクトにフェッチ制限を設定する場合、これらのケースでは「行フェッチ制限」設定は無視されます。「行フェッチ制限」の詳細は、「ビュー・オブジェクトの最大フェッチ・レコード数を制限するためのフェッチ・サイズの使用方法」を参照してください。

転送専用モード

データセットのトラバースで転送しか実行されない場合は、転送専用モードを使用すると、データセットを反復する場合のパフォーマンスが向上します。転送専用モードは、ビュー・オブジェクトでsetForwardOnly(true)をコールしてプログラム的に設定できます。転送専用モードを設定すると、データセットがトラバースされるときに、前の行セットがキャッシュされるのを防ぐこともできます。

ビュー・オブジェクトをチューニングする場合は、次の点も考慮する必要があります。

  • 大規模なデータ・セット: ビュー・オブジェクトは、ユーザーが結果の特定のページにジャンプできるように、大規模なデータ・セット内でページ移動するメカニズムを備えています。この機能は、ビュー・オブジェクトでsetRangeSize(n)setAccessMode(RowSet.RANGE_PAGING)の順にコールすることによって設定します(nは、1ページに含める行数)。ユーザーがデータ・セット内の特定のページに移動する場合、アプリケーションはビュー・オブジェクトでscrollToRangePage(P)をコールするとページPに移動できます。範囲ページングでは、現在のページの行のみがフェッチされて、ビュー・オブジェクトの行キャッシュに入れられるため、1ページのデータを取得するたびに問合せ実行のコストがかかります。範囲ページングは、すべての行をフェッチしてビュー・オブジェクトの行キャッシュに入れるほうが有利な場合には適していません(たとえば、データ・セットのすべての行を読み取ってLOVを生成したり、小さいデータ・セットのレコードを前後にページ移動したりする必要がある場合です)。

  • スピルオーバー: JVMコンテナでメモリーが不足した場合に、データ・ソースを仮想メモリーとして使用する機能が用意されています。デフォルトでは、この機能は無効になっていますが、メモリーが不足した場合の最後の手段として、jbo.use.pers.coll=trueに設定することにより有効にできます。スピルオーバーを有効にすると、パフォーマンスが大きく影響を受ける場合があります。

  • SQLプラットフォーム: SQL92準拠の汎用データベースへの接続に汎用SQL92 SQLプラットフォームを使用すると、ビュー・オブジェクトの一部のチューニング・オプションが正常に機能しなくなります。汎用SQL92 SQLプラットフォームを選択することにより最も影響を受けるパラメータは、フェッチ・サイズです。SQL92 SQLプラットフォームを使用すると、ビュー・オブジェクトの構成に関係なく、フェッチ・サイズがデフォルトで10行に設定されます。SQLプラットフォームは、データベース接続を定義するときに設定したり、adf-config.xmlファイル内にグローバルなプロジェクト設定として定義できます。デフォルトでは、SQLプラットフォームはOracleになります。SQLプラットフォームを手動でオーバーライドする場合は、起動時にパラメータ-Djbo.SQLBuilder="SQL92"をJVMに渡すこともできます。

また、データベースのパフォーマンスを向上するために、ビュー・オブジェクトの関連するSQLをチューニングするための次のオプションも用意されています。

  • バインド変数: ビュー・オブジェクトに関連付けられた問合せに、実行ごとに変更される可能性がある値が含まれる場合は、バインド変数を使用します。問合せでバインド変数を使用すると、データベースで問合せを再解析する必要なく、問合せを再実行できます。バインド変数は、ビュー・オブジェクトの概要エディタの「問合せ」ページでビュー・オブジェクトに追加できます。詳細は、「バインド変数の使用」を参照してください。

  • 問合せオプティマイザ・ヒント: ビュー・オブジェクトでは、ヒントをデータベースに渡して、関連する問合せに使用される実行計画に影響を与えることができます。オプティマイザ・ヒントは、ビュー・オブジェクトの概要エディタの「チューニング」セクションの「データベースから取得」グループ・ボックスで指定できます。オプティマイザ・ヒントの詳細は、「必要に応じた問合せオプティマイザ・ヒントの指定」を参照してください。

ビュー・オブジェクト・インスタンスのプログラムによるテスト

クライアント・プログラムを使用してADFアプリケーション・モジュールをプラグラム的にテストします。

少なくとも1つのビュー・オブジェクト・インスタンスを含む、操作中のアプリケーション・モジュールをテストする準備ができたら、単純なテスト・クライアント・プログラムを構築して、含まれるビュー・オブジェクト・インスタンスにあるデータを使用したプログラムによる操作の基礎を示すことができます。

アプリケーション・モジュールのデータ・モデルにアクセスするクライアントの視点からは、読取り専用ビュー・オブジェクトを操作するAPIと、エンティティ・ベースのビュー・オブジェクトを操作するAPIは同一のものです。機能的な主な相違点は、エンティティ・ベースのビュー・オブジェクトでは、ビュー・オブジェクトのデータを完全に更新できる点です。エンティティ・ベースのビュー・オブジェクトを含むアプリケーション・モジュールは、作業ユニットを定義し、トランザクションを管理します。この項では、SummitADF_Examplesワークスペースを操作するテスト・クライアント・プログラムを使用して次について説明します。

  • マスター/ディテール/ディテール階層の反復

  • 行の検索および外部キー値の更新

  • 新規注文の作成

  • 行を識別する行キーの取得

ビュー・オブジェクトのデフォルト行セットを使用した操作のViewObjectインタフェース・メソッド

oracle.jboパッケージのViewObjectインタフェースには、データ取得タスクを簡単に実行するメソッドが用意されています。例に使用されるこれらのメソッドの一部には、次のものが含まれます。

  • executeQuery(): ビュー・オブジェクトの問合せを実行し、その結果の行セットを移入します。

  • setWhereClause(): 実行時に動的条件を追加して検索を絞り込みます。

  • setNamedWhereClauseParam(): 名前付きバインド変数の値を設定します。

  • hasNext(): 行セット・イテレータが結果の最終行に到達したかどうかをテストします。

  • next(): 行セット・イテレータを行セット内の次の行へ進めます。

  • getEstimatedRowCount(): ビュー・オブジェクトの問合せが戻す行の数をカウントします。

ビュー・オブジェクトを操作する場合は、通常、単一の結果行セットのみを1回で操作します。このきわめて一般的なユースケースを単純化するために、図8-18に示すように、ビュー・オブジェクトにはデフォルトのRowSetが含まれ、ここにデフォルトのRowSetIteratorが含まれています。デフォルトのRowSetIteratorにより、デフォルト行セットに自動的に適用されることを認識しながら、ViewObjectコンポーネント自体でデータ取得メソッドのすべてを直接コールできるようになります。

図8-18 デフォルトのRowSetおよびRowSetIteratorが含まれているビュー・オブジェクト

この図は周囲のテキストで説明しています

ノート:

「多相ビュー・オブジェクトの定義」では、単一のビュー・オブジェクトを使用して複数の異なる結果行セットを生成する状況が示されています。また、1つの行セットに対して複数の異なる行セット・イテレータを作成するシナリオも説明されています。ただし、多くの場合は単一のイテレータのみ必要です。

このガイドで「ビュー・オブジェクトの行を使用して操作中」という表現を使用した場合は、正確にはビュー・オブジェクトのデフォルト行セットの行を使用して操作するということを意味しています。同様に、「ビュー・オブジェクトの行全体で反復処理する」という表現は、正確にはビュー・オブジェクトのデフォルト行セットのデフォルト行セット・イテレータを使用して、その行をループするという意味です。

ビュー行またはエンティティ行におけるキー・オブジェクトの役割

ビュー行を操作するときは、oracle.jboパッケージの中のRowインタフェースを使用します。図8-19に示すように、このインタフェースには、任意の行を識別するKeyオブジェクトへのアクセスに使用できる、getKey()と呼ばれるメソッドが含まれています。Rowインタフェースは、oracle.jbo.serverパッケージ内の Entityインタフェースによって拡張されます。この関係は、エンティティ行という用語が適切であることの具体的な理由になります。エンティティ行がビジネス・ロジックのカプセル化やデータベース・アクセスの処理のための追加機能をサポートしている場合でも、エンティティ行はRowとしてそのまま扱うことができます。

エンティティ・ベースのビュー・オブジェクトは、キーによる行の検索タスクを、基礎となるエンティティ行部分に委譲します。

前述のとおり、ビュー行とエンティティ行はどちらも単一属性または複数属性のキーをサポートしているため、特定のRowに関連付けられたKeyオブジェクトにより、キーを構成するすべての属性がカプセル化されます。Keyオブジェクトがある場合は、任意の行セットに対してfindByKey()メソッドを使用して、Keyオブジェクトに基づいて行を検索できます。findByKey()メソッドを使用してキーによってビュー行を検索すると、ビュー行ではエンティティ定義のfindByPrimaryKey()メソッドを使用して、ビュー行キーに属性を提供する各エンティティ行が検索されます。

読取り専用ビュー・オブジェクトの場合、このタスクを委譲する基礎となるエンティティ行がないため、主キー属性が1つでも検出されると、ビュー・オブジェクトの実装により、manageRowsByKeyフラグが自動的に有効になります。このため、読取り専用ビュー・オブジェクトの場合は、findByKey()メソッドが成功します。manageRowsByKeyフラグが有効でない場合、キーを使用して現在の行を設定するなどのUI操作は、findByKey()メソッドに依存するため機能しません。

図8-19 識別キーの取得をサポートしているビュー行またはエンティティ行

例8-19の説明が続きます
「図8-19 識別キーの取得をサポートしているビュー行またはエンティティ行」の説明

ノート:

エンティティ・ベースのビュー・オブジェクトを定義する場合、デフォルトでは、すべてのエンティティ・オブジェクトの慣用名の主キー属性は、「キー属性」プロパティの設定がtrueとしてマークされます。更新不可能な参照エンティティ・オブジェクトの慣用名では、キー属性の「キー属性」プロパティを無効にしてください。更新可能なエンティティ・オブジェクトの慣用名の主キーに関連するビュー・オブジェクト属性は、複合ビュー行キーの一部である必要があるため、「キー属性」プロパティを無効にできません。

エンティティ・キャッシュがトランザクションで果す役割

アプリケーション・モジュールは、論理的な作業ユニットのトランザクション・コンテナです。実行時には、指定された名前の構成情報を使用してデータベース接続を確立し、トランザクション管理を付属のTransactionオブジェクトに委譲します。論理作業ユニットには、様々なタイプの複数のエンティティ行の検索や変更が含まれる場合があるため、Transactionオブジェクトには、現在のユーザーのトランザクションに関連するエンティティ行を保持するための作業領域として、エンティティ・キャッシュが用意されています。各エンティティ・キャッシュには単一のエンティティ・タイプの行が含まれるため、2つ以上のエンティティ・オブジェクトが関連するトランザクションでは、これらのエンティティ行の作業用コピーが個別キャッシュに保持されます。

エンティティ・オブジェクトの関連エンティティ定義を使用して、アプリケーション・モジュールで既存のエンティティ行を検索し、変更するためのコードを記述できます。図8-20に示すとおり、Orderエンティティ・オブジェクトのエンティティ定義に対してfindByPrimaryKey()をコールすると、そのキーを持つ行を取得できます。この行がまだエンティティ・キャッシュ内にない場合、エンティティ・オブジェクトによってこの行をデータベースから取得するための問合せが実行されます。この問合せにより、基礎となる表からエンティティ・オブジェクトのすべての持続属性が選択され、エンティティ・オブジェクトの主キー属性に対応する列に適したWHERE句を使用して行が検索されます。同一トランザクション中に同じエンティティ行をキーによって引き続き検索する場合、この行をキャッシュ内で検索することにより、データベースへのトリップを回避します。特定のエンティティ・キャッシュでは、主キーによってエンティティ行が索引付けされます。これにより、キャッシュ内でのエンティティ行の検索処理が速くなります。

アソシエーション・アクセッサ・メソッドを使用して関連エンティティ行にアクセスする場合、これらの行はエンティティ・キャッシュからも取得されます。関連エンティティ行がキャッシュ内にない場合は、データベースから取得されます。最後に、エンティティ・キャッシュは、新しいエンティティ行が保存されるまで保持される場所でもあります。つまり、createInstance2()メソッドを使用してエンティティ定義に対して新しいエンティティ行を作成する場合、このエンティティ行はエンティティ・キャッシュに追加されます。

図8-20 トランザクション中にエンティティ・キャッシュに格納されるエンティティ行

例8-20の説明が続きます
「図8-20 トランザクション中にエンティティ・キャッシュに格納されるエンティティ行」の説明

エンティティ行を作成、変更または削除すると、このエンティティ行はトランザクションの保留中の変更リストに自動的に登録されます。Transactionオブジェクトに対してcommit()をコールすると、保留中の変更リストが処理され、まだ無効の新規または変更済エンティティ行があるかどうかが検証されます。保留リスト内のエンティティ行がすべて有効である場合、Transactionにより、データベースのSAVEPOINTが発行され、データベースへのエンティティ行の保存が調整されます。すべて正常に完了すると、最終的にデータベースのCOMMIT文が発行されます。問題が発生した場合、TransactionによってROLLBACK TO SAVEPOINTが実行され、ユーザーはエラーを修正するか、または再試行できるようになります。

アプリケーション・モジュールで使用されるTransactionオブジェクトは、単一のエンド・ユーザー・トランザクション用のエンティティ行の作業セットです。設計上、これは共有のグローバル・キャッシュではありません。データベース・エンジン自体は、複数の同時ユーザーを対象とした非常に効率的な共有グローバル・キャッシュです。ADFビジネス・コンポーネントでは、すべての作業で行われてきたデータベースの共有グローバル・キャッシュ機能の微調整を繰り返すのではなく、その結果が意識的に採用されています。refresh()メソッドをコールすると、データベースから単一のエンティティ・オブジェクトのデータをいつでもリフレッシュできます。Transactionオブジェクトに対してsetClearCacheOnCommit()またはsetClearCacheOnRollback()を使用すると、コミットまたはロールバック時にエンティティ・キャッシュを消去するかどうかを制御できます。デフォルトはそれぞれfalsetrueです。また、TransactionオブジェクトにはclearEntityCache()メソッドも用意されており、このメソッドを使用して、特定のエンティティ・タイプ(またはすべてのタイプ)のエンティティ行をプログラムで消去できます。エンティティ・キャッシュをクリアすると、そのタイプのエンティティ行は、主キーによって次に検出されるか、エンティティ・ベースのビュー・オブジェクトによって取得されるときに、データベースから取得できます。

コマンド行Javaテスト・クライアントの作成方法

テスト・クライアント・プログラムを作成するには、「新規ギャラリ」からアクセス可能な「Javaクラスの作成」ウィザードを使用します。

スケルトン・コードを使用したテスト・クライアントの作成

テスト・クライアント・プログラムを作成するときに「Javaクラスの作成」ウィザードを使用すると、プログラム・ファイルがソース・エディタで開き、事前定義済のコード・テンプレートからコードを追加してテスト・クライアントを作成することができます。

始める前に:

プログラムによるテストに関する知識が役立つ場合があります。詳細は、「ビュー・オブジェクト・インスタンスのプログラムによるテスト」を参照してください。

他のOracle ADF機能を使用して追加できる機能を理解しておくことも役立ちます。詳細は、「ビュー・インスタンスのテストの追加機能」を参照してください。

スケルトンJavaテスト・クライアントを作成するには:

  1. 「アプリケーション」ウィンドウで、テスト・クライアントを作成するプロジェクトを右クリックし、「新規」「Javaクラス」の順に選択します。
  2. 「Javaクラスの作成」ダイアログで、クラス名とパッケージ名を入力し、「拡張」フィールドがjava.lang.Objectとなっていることを確認します。
  3. 「オプション属性」で、「スーパークラスからのコンストラクタ」の選択を解除し、「mainメソッド」を選択します。
  4. 「OK」をクリックします。

    .javaはソース・エディタで開き、次の例に示すように、スケルトン・コードが示されます。この例では、TestClientがクラス名で、oracle.summit.model.testがパッケージ名です。

package oracle.summit.model.test;

public class TestClient {
  public static void main(String[] args) {
     TestClient testClient = new TestClient();
  }
}
スケルトン・コードの変更によるテスト・クライアントの作成

テスト・クライアントのスケルトン・コードを作成したら、作成したスケルトン・コード・テンプレートを使用してファイルの編集を開始できます。

始める前に:

プログラムによるテストに関する知識が役立つ場合があります。詳細は、「ビュー・オブジェクト・インスタンスのプログラムによるテスト」を参照してください。

他のOracle ADF機能を使用して追加できる機能を理解しておくことも役立ちます。詳細は、「ビュー・インスタンスのテストの追加機能」を参照してください。

次のタスクを完了する必要があります。

スケルトン・コードを挿入するには:

  1. main()メソッドの本体にある空白行にカーソルを置き、テスト・クライアント・クラス名を入力して、[Ctrl]キーを押しながら[Enter]キーを押します。
  2. bc4jclientという文字を入力し、[Ctrl]キーを押しながら[Enter]キーを押します。
  3. amDefおよびconfig変数の値を調整して、アプリケーション・モジュール定義の名前と使用する構成の名前をそれぞれ反映します。

    次の例では、変更した行は次のようになります。

    String amDef = "oracle.summit.model.viewobjects.AppModule";
    String config = "AppModuleLocal";
    
  4. 最後に、コール内のビュー・オブジェクト・インスタンス名を、作業するfindViewObject()に変更します。アプリケーション・モジュールの概要エディタの「データ・モデル」ページで「データ・モデル」ツリーに表示される名前を正確に指定します。

    変更後の行は次のようになります。

    ViewObject customerList = am.findViewObject("SCustomerView1");

アプリケーション・モジュールに対するスケルトン・テスト・クライアントには、次の例に示すようなソース・コードが含まれている必要があります。

ノート:

「アプリケーション・モジュールのクライアント・インタフェースのプログラム的操作」における例では、このテスト・クライアント・サンプルコードが拡張され、カスタム・アプリケーション・モジュール・サービス・メソッドのコールも説明されます。

package oracle.summit.model.viewobjects;

import oracle.jbo.ApplicationModule;
import oracle.jbo.Row;
import oracle.jbo.RowSet;
import oracle.jbo.ViewObject;
import oracle.jbo.client.Configuration;

public class TestClient {

  public static void main(String[] args) {
    String  amDef = "oracle.summit.model.viewobjects.AppModule";
    String  config = "AppModuleLocal";
    ApplicationModule am =
                      Configuration.createRootApplicationModule(amDef,config);
    // 1. Find the Customer view object instance.
    ViewObject customerList = am.findViewObject("SCustomerView1");
    // Work with your appmodule and view object here
    Configuration.releaseRootApplicationModule(am,true);
  }
}

メソッド・コールcreateRootApplicationModule()により、テスト・クライアントは、ADFモデル・レイヤーが使用できない場所でアプリケーション・モジュール・インスタンスを作成できます。通常、Fusion Webアプリケーションでは、コードはADFバインディング・オブジェクトを介してアプリケーション・モジュール上のビュー・オブジェクトを見つけます。ADFモデル・レイヤーの操作方法の詳細は、「Fusion Webアプリケーションでのアプリケーション・モジュール・クライアント・インタフェースへのアクセス方法」を参照してください。

// Work with your appmodule and view object hereを、テスト対象のビュー・オブジェクトを実行するコードに置き換えます。たとえば、ビュー・オブジェクトの問合せを実行して戻される行数を表示し、結果をループしてデータをフェッチし、コンソールに出力するには、次の例に示すコードを、使用しているデータ・モデル・プロジェクトのコンポーネントに合うように変更します。

    // 2. Execute the query
    customerList.executeQuery();
    // 3. Iterate over the resulting rows
    while (customerList.hasNext()) {
        Row customer = customerList.next();
        // 4. Print the customer's name
        System.out.println("Customer: " + customer.getAttribute("Name"));
        // 5. Get related rowset of Orders using view link accessor attribute
        RowSet orders = (RowSet)customer.getAttribute("SOrdView");
        // 6. Iterate over the Orders rows
        while (orders.hasNext()) {
            Row order = orders.next();
            // 7. Print out some order attribute values
              System.out.println(" ["+order.getAttribute("CustomerId")+"] "+
                                    order.getAttribute("Id")+": "+
                                    order.getAttribute("Total"));
              if(!order.getAttribute("OrderFilled").equals("Y")) {
                  // 8. Get related rowset of OrderItems
                  RowSet items = (RowSet)order.getAttribute("SItemView");
                  // 9. Iterate over the OrderItems rows
                  while (items.hasNext()) {
                     Row item = items.next();
                     // 10. Print out some order items attributes
                     System.out.println("  "+item.getAttribute("ItemId")+": "+
                                          item.getAttribute("Price"));
                }
            }
        }
    }

最初の行では、executeQuery()メソッドをコールして、ビュー・オブジェクト問合せを実行します。これにより、ビュー・オブジェクトのhasNext()メソッドがfalseを戻すまで反復処理を行うwhile文を使用してループできる、ゼロまたは1行以上の行セットを生成します。ループ内では、コードで現行のRowcustomerという変数に入れてから、この現在のRowオブジェクト上でgetAttribute()メソッドを2回コールし、Name属性とOrders属性の値を取得して、オーダー情報をコンソールに出力します。2番目のwhile文では、オーダーの明細項目に対して同じタスクを実行します。

テスト・クライアント・プログラム実行時の処理

ConfigurationオブジェクトでのcreateRootApplicationModule()へのコールによって、使用するアプリケーション・モジュールのインスタンスが戻されます。デバッグ診断出力で示されるとおり、ADFビジネス・コンポーネント・ランタイム・クラスによって、必要に応じてXMLドキュメントがロードされ、設計時にデータ・モデルで定義されたアプリケーション・モジュールとビュー・オブジェクト・コンポーネントのインスタンスがインスタンス化されます。アプリケーション・モジュール上のfindViewObject()メソッドによって、アプリケーション・モジュールのデータ・モデルからビュー・オブジェクト・インスタンスを名前で検索します。「スケルトン・コードの変更によるテスト・クライアントの作成」で示されているループの後、テスト・クライアントはConfigurationオブジェクトでreleaseRootApplicationModule()を実行します。これにより、アプリケーション・モジュールを使用して処理したことが通知され、アプリケーション・モジュールに使用されたデータベース接続のように、フレームワークでリソースをクリーン・アップできるようになります。

テスト・クライアントの実行に関する必知事項

createRootApplicationModule()およびreleaseRootApplicationModule()メソッドは、アプリケーション・モジュール・コンポーネントへのコマンド行アクセスの場合に非常に便利です。ただし、通常、ADFベースのWebアプリケーションのコンテキストでは、これら2行のコードを記述する必要はありません。このような場合は、ADFモデル・レイヤーとADFビジネス・サービス・レイヤーの自動的な連携により、ADFアプリケーション・モジュール・コンポーネントが取得およびリリースされます。ADFモデル・レイヤーの操作方法の詳細は、「Fusion Webアプリケーションでのアプリケーション・モジュール・クライアント・インタフェースへのアクセス方法」を参照してください。

行セットにおける行数計算の方法

getEstimatedRowCount()メソッドは、含まれている行数を判断するために、RowSetで使用されます。

long numOrders = orders.getEstimatedRowCount();

getEstimatedRowCount()の実装によって最初にSELECT COUNT(*)の問合せが発行され、問合せから戻される行の数を計算します。問合せは、次のような文のビュー・オブジェクトの問合せ全体をラップすることにより、計算式で表されます。

SELECT COUNT(*) FROM ( ... your view object's SQL query here ... )

SELECT COUNT(*)問合せを使用すると、必ずしもすべての行自体を取得しなくても、ビュー・オブジェクトの行数にアクセスできるようになります。このアプローチにより、大量の行数を戻す問合せを操作する場合や、問合せの結果を操作する前に問合せから戻さうる行数をテストする場合に、重要な最適化を図ることができます。

推定行数が計算されると、後続のメソッドへのコールではCOUNT(*)問合せは再実行されません。この値は、次にこのビュー・オブジェクトの問合せが実行されるまでキャッシュされます(データベースから戻される新しい問合せ結果セットに、前回の問合せ実行時より多い、少ない、または異なる行が含まれる可能性があるためです)。推定行数は、現行トランザクションで保留中の変更、関連する新規行の数の追加、および戻された数から削除された行数の差引を考慮して自動的に調整されます。

getEstimatedRowCount()をオーバーライドして、アプリケーションの必要性に合せて、カスタムのカウント問合せを実行することもできます。

ビュー・リンク・アクセッサを使用したディテール・コレクションのアクセス方法

「ビュー・リンク・アクセッサを使用したディテール・コレクションへのプログラムによるアクセス」で説明しているように、ビュー・リンク・アクセッサを使用してディテール行のRowSetを取得すると、ビュー・オブジェクトの結果行セットで使用されるパターンと同じパターンを使用して、その行セットに含まれる行全体をループできます(次の例を参照)。

while (orders.hasNext()) {
  Row curOrder = orders.next();
  System.out.println("--> (" + curOrder.getAttribute("Id") + ") " + 
                     curOrder.getAttribute("Total"));
}

次の例は、CustomerViewビュー・オブジェクト・インスタンスを制限してcredit_rating_idの値が4であるユーザーのみを表示するために、動的なWHERE句を設定するmain()メソッドを示しています。さらに、executeAndShowResults()メソッドは、ビュー・リンク・アクセッサ属性(SOrdView)にアクセスし、各顧客のオーダーのIdおよびTotal属性を出力します。

ビュー・リンク・アクセッサを使用してディテール・コレクションにアクセスするには、次の基本ステップに従います(後に例を示しています)。

  1. マスター・ビュー・オブジェクト・インスタンスを検索します。

  2. 問合せを実行します。

  3. マスター・ビュー・オブジェクトの行を反復処理します。

  4. ビュー・リンク・アクセッサ属性を使用して、関連するディテール・ビュー・オブジェクトの行セットを取得します。

  5. ディテール・ビュー・オブジェクトの行を反復処理します。

  6. 必要に応じて、ディテール行セット属性を操作します。

パフォーマンスのヒント:

行をループするために記述するコードで行を表示する必要がない場合は、終了した行セットでcloseRowSet()メソッドをコールできます。この方法では、メモリー使用を効率化できます。行セットの問合せは、その行セットに次にアクセスしたときに再実行されます。

package oracle.summit.model.viewobjects;

import oracle.jbo.ApplicationModule;
import oracle.jbo.Row;
import oracle.jbo.RowSet;
import oracle.jbo.ViewObject;
import oracle.jbo.client.Configuration;

public class TestClient2 {
    public static void main(String[] args) {
            String        amDef = "oracle.summit.model.viewobjects.AppModule";
            String config = "AppModuleLocal";
            ApplicationModule am = 
                Configuration.createRootApplicationModule(amDef, config);
            ViewObject vo = am.findViewObject("SCustomerView1");
          // Add an extra where clause with a new named bind variable
            vo.setWhereClause("credit_rating_id = :theCreditRating");
            vo.defineNamedWhereClauseParam("theCreditRating", null, null);
            vo.setNamedWhereClauseParam("theCreditRating", "4");
          // Show results when :theCreditRating = '4'
          executeAndShowResults(vo);
          Configuration.releaseRootApplicationModule(am, true);
        }
        private static void executeAndShowResults(ViewObject vo) {
          System.out.println("---");
          vo.executeQuery();
          while (vo.hasNext()) {
            Row curCustomer = vo.next();
            // Access the row set of details using the view link accessor attr.
            RowSet orders = (RowSet)curCustomer.getAttribute("SOrdView");
            long numOrders = orders.getEstimatedRowCount();
            System.out.println(curCustomer.getAttribute("Id") + " " + 
                               curCustomer.getAttribute("Name")+" ["+
                               numOrders+" orders]");
            while (orders.hasNext()) {
              Row curOrder = orders.next();
              System.out.println("--> (" + curOrder.getAttribute("Id") + ") " + 
                                 curOrder.getAttribute("Total"));
            }
          }
        }
}

TestClient2.javaを実行すると、次の例に示すような出力が「ログ」ウィンドウに出力されます。各顧客がリストされ、オーダーのある顧客ごとに、オーダーのIDと合計が顧客名の下に表示されます。

---
202 Simms Athletics [11 orders]
--> (98) 595
--> (113) 4990
--> (114) 567
--> (115) 866.7
--> (116) 3661.24
--> (117) 17489
212 Hamada Sport [22 orders]
--> (108) 149570
--> (196) 761
--> (197) 516.75
...

デバッグ診断を有効にしてTestClient2.javaを実行すると、ビュー・オブジェクトによって実行されたSQL問合せが表示されます。ビュー・リンクのWHERE句条件は、CustomerViewビュー・オブジェクトで現在行のディテール・サービス・リクエスト行のフィルタリングを自動実行するために使用されます。

マスター/ディテール/ディテール階層の反復方法

別のネスト・レベルが含まれるマスター/ディテールの反復処理を行うには、次の基本ステップに従います(後に例を示しています)。

  1. マスター・ビュー・オブジェクト・インスタンスを検索します。

  2. 問合せを実行します。

  3. 結果の行を反復処理します。

  4. 必要に応じて、マスター行セット属性を操作します。

  5. ビュー・リンク・アクセッサ属性を使用して、関連するディテール・ビュー・オブジェクトの行セットを取得します。

  6. ディテール行セットの行を反復処理します。

  7. 必要に応じて、ディテール行セット属性を操作します。

  8. ビュー・リンク・アクセッサ属性を使用して、関連する2番目のディテール・ビュー・オブジェクトの行セットを取得します。

  9. 2番目のディテール・行セットの行を反復処理します。

  10. 必要に応じて、2番目のディテール行セット属性を操作します。

次の例では、もう1つネスト・レベルが追加されている以外は、「ビュー・リンク・アクセッサを使用したディテール・コレクションのアクセス方法」で説明した、マスター/ディテール読取り専用ビュー・オブジェクトを反復するTestClientプログラムと同じAPIを使用しています。

既存のTestClient.javaクラスでJDeveloperの「リファクタ」→「複製」機能を使用する場合、それを簡単にクローニングしてTestClient2.javaクラスを作成できます。たとえば、「ビュー・リンク・アクセッサを使用したディテール・コレクションのアクセス方法」で説明しているTestClient.javaクラスはこの手法に適しています。

package oracle.summit.model.viewobjects;

import oracle.jbo.ApplicationModule;
import oracle.jbo.Row;
import oracle.jbo.RowSet;
import oracle.jbo.ViewObject;
import oracle.jbo.client.Configuration;

public class TestClient {
    public static void main(String[] args) {
        TestClient testClient = new TestClient();
        String amDef = "oracle.summit.model.viewobjects.AppModule";
        String config = "AppModuleLocal";
        ApplicationModule am = 
                          Configuration.createRootApplicationModule(amDef,config);
        // Work with your appmodule and view object here
        // 1. Find the Customer view object instance.
        ViewObject customerList = am.findViewObject("SCustomerView1");
        // 2. Execute the query
          customerList.executeQuery();
          // 3. Iterate over the resulting rows
          while (customerList.hasNext()) {
              Row customer = customerList.next();
              // 4. Print the person's email
              System.out.println("Customer: " + customer.getAttribute("Name"));
              // 5. Get related rowset of Orders using view link accessor attr.
              RowSet orders = (RowSet)customer.getAttribute("SOrdView");
              // 6. Iterate over the Orders rows
              while (orders.hasNext()) {
                  Row order = orders.next();
                  // 7. Print out some order attribute values
                    System.out.println(" ["+order.getAttribute("CustomerId")+"] "+
                                          order.getAttribute("Id")+": "+
                                          order.getAttribute("Total"));
                    if(order.getAttribute("OrderFilled").equals("Y")) {
                        // 8. Get related rowset of Items
                        RowSet items = (RowSet)order.getAttribute("SItemView");
                        // 9. Iterate over the Items rows
                        while (items.hasNext()) {
                           Row item = items.next();
                           // 10. Print out some order items attributes
                           System.out.println("  "+
                                                item.getAttribute("ItemId")+": $"+
                                                item.getAttribute("Price"));
                      }
                  }
              }
          }
    }
}

このプログラムを実行すると、次の例に示す出力が生成されます。

Customer: Unisports
 [201] 97: 84000
  210: $9
  211: $1500
Customer: Simms Athletics
 [202] 98: 595
  212: $85
 [202] 113: 4990
  328: $9
 [202] 114: 567
  329: $28
  330: $40.95
  331: $25
...

行の検索および外部キー値の更新の方法

行を検索して外部キーの値を更新するには、次の基本ステップに従います(後に例を示しています)。

  1. ビュー・オブジェクト・インスタンスを検索します。

  2. Keyオブジェクトを作成し、ビュー・インスタンスの行を参照します。

  3. findByKey()を使用して行を検索します。

  4. 必要に応じて、行の属性を操作します。

次の例は、外部キーの値を検索して更新し、Ordersビュー・オブジェクト・インスタンスの行を検索するmain()メソッドを示しています。このサンプルでは、行の値が変更される前に、既存のOrderStatusCode属性の値が出力されます。

package oracle.summit.model.viewobjects;
 
import java.text.ParseException;
import java.text.SimpleDateFormat;
 
import java.util.Calendar;
import java.util.Date;
 
import oracle.jbo.ApplicationModule;
import oracle.jbo.JboException;
import oracle.jbo.Key;
import oracle.jbo.Row;
import oracle.jbo.RowSet;
import oracle.jbo.ViewObject;
import oracle.jbo.client.Configuration;
 
public class TestClient3 {
    public TestClient3() {
        super();
    }
 
    public static void main(String[] args) {
        String amDef = "oracle.summit.model.viewobjects.AppModule";
        String config = "AppModuleLocal";
        ApplicationModule am = 
                         Configuration.createRootApplicationModule(amDef, config);
        // 1. Find the Orders view object instance
        ViewObject vo = am.findViewObject("SOrdView1");
        // 2. Construct a new Key to find Order # 100
        Key orderKey = new Key(new Object[] { 100 });
        // 3. Find the row matching this key
        Row[] ordersFound = vo.findByKey(orderKey, 1);
        if (ordersFound != null && ordersFound.length > 0) {
            Row order = ordersFound[0];
            // 4. Print some order information
            Date dateOrdered = (Date) order.getAttribute("DateOrdered");
            String orderDate = dateOrdered.toString();
            System.out.println("Order Date is: " + orderDate);
 
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); 
            Calendar c = Calendar.getInstance();
            try {
                c.setTime(sdf.parse(orderDate));
            } catch (ParseException e) {
            }
            c.add(Calendar.DAY_OF_MONTH, -2);  
            // // number of days to add 
            orderDate = sdf.format(c.getTime());  
            System.out.println(orderDate);
            try {
                // 5. Try setting the ship date to an illegal value
                order.setAttribute("DateShipped", orderDate);
                am.getTransaction().commit();
            } catch (JboException ex) {
                System.out.println("ERROR: " + ex.getMessage());
            }
            // 6. Set the ship date to a legal value
            order.setAttribute("DateShipped", orderDate);
            // 7. Show the value of the ship date was updated successfully
            System.out.println("Ship date is: " +
                                             order.getAttribute("DateShipped"));
            // 8. Show the current value of the customer for this order
            System.out.println("Customer: " + order.getAttribute("CustomerId"));
            // 9. Reassign the order to customer # 210
            order.setAttribute("CustomerId", 210);
            // 10. Show the value of the reference information now
            System.out.println("Customer: " + order.getAttribute("CustomerId"));
            // 11. Rollback the transaction
            am.getTransaction().rollback();
            System.out.println("Transaction canceled");
        }
        Configuration.releaseRootApplicationModule(am, true);
    }
 
}

この例を実行すると、次の例に示す出力が生成されます。

Order Date is: 2012-08-29
2012-08-27
ERROR: JBO-oracle.summit.model.viewobjects.SOrd_Rule_0: 
       You cannot have a shipping date that is before the order date
Ship date is: 2012-08-27
Customer: 204
Customer: 210
Transaction canceled

ビュー・オブジェクト・インスタンスの新しい行の作成方法

新しいビュー行インスタンスを作成するには、次の基本ステップに従います(後に例を示しています)。

  1. ビュー・オブジェクト・インスタンスを検索します。

  2. 新しい行を作成し、行セットに挿入します。

  3. 新しい行の必須属性の値を設定します。

  4. トランザクションをコミットします。

次の例は、OrdViewビュー・オブジェクト・インスタンスを検索し、新しい行を行セットに挿入するmain()メソッドを示しています。OrdViewビュー・オブジェクトはエンティティ・ベースなので、CreatedBy属性は、マップされたエンティティ・オブジェクト属性から値を導出します。このサンプルでは、トランザクションのコミット前に、残りの属性の値が設定されます。

package oracle.summit.model.viewobjects;

import java.util.Date;

import oracle.jbo.ApplicationModule;
import oracle.jbo.Row;
import oracle.jbo.ViewObject;
import oracle.jbo.client.Configuration;
import oracle.jbo.domain.DBSequence;

public class TestClient4 {
 
  public static void main(String[] args) {
        String amDef = "oracle.summit.model.viewobjects.AppModule";
        String config = "AppModuleLocal";
        ApplicationModule am = 
                         Configuration.createRootApplicationModule(amDef, config);

        // 1. Find the Orders view object instance.
        ViewObject orders = am.findViewObject("SOrdView1");

        // 2. Create a new row and insert it into the row set
        Row newOrder = orders.createRow();
        orders.insertRow(newOrder);
        // Show the entity object-related defaulting for DateOrdered attribute
        System.out.println("DateOrdered defaults to: " + 
                                    newOrder.getAttribute("DateOrdered"));

        // 3. Set values for some of the required attributes        
        newOrder.setAttribute("CustomerId", 201);
        newOrder.setAttribute("SalesRepId", 12);
        newOrder.setAttribute("PaymentTypeId", 2);
        newOrder.setAttribute("OrderFilled", "N");

        // 4. Commit the transaction
        am.getTransaction().commit();

        // 5. Retrieve and display the trigger-assigned order id
        DBSequence id = (DBSequence)newOrder.getAttribute("Id");
        System.out.println("Thanks, reference number is " +
                                                  id.getSequenceNumber());
        Configuration.releaseRootApplicationModule(am, true);
  }
}

この例を実行すると、次の例に示す結果が生成されます。

DateOrdered defaults to: 2013-3-11
Thanks, reference number is 6

行を識別する行キーの取得方法

行キーを取得して行を特定するには、次の基本ステップに従います(後に例を示しています)。

  1. ビュー・オブジェクト・インスタンスを検索します。

  2. 指定された値を使用してキーを作成します。

  3. このキーを使用して行を検索します。

  4. 必要に応じて、行のキーを操作します。

次の例は、OrdViewビュー・オブジェクト・インスタンスを検索し、行キーを作成してオーダー番号を検索するmain()メソッドを示しています。findByKey()メソッドでは、指定されたキーによりOrdView行が検索されます。このサンプルでは、次に行のキーが表示され、ItemViewビュー・リンク・アクセッサを使用して行セットがアクセスされ、行を反復処理して各ItemView行のキーが表示されます。

package oracle.summit.model.viewobjects;
 
import oracle.jbo.ApplicationModule;
import oracle.jbo.Key;
import oracle.jbo.Row;
import oracle.jbo.RowSet;
import oracle.jbo.ViewObject;
import oracle.jbo.client.Configuration;
 
public class TestClient5 {
    public static void main(String[] args) {
        String amDef = "oracle.summit.model.viewobjects.AppModule";
        String config = "AppModuleLocal";
        ApplicationModule am = 
                         Configuration.createRootApplicationModule(amDef, config);
        // 1. Find the Orders view object instance
        ViewObject vo = am.findViewObject("SOrdView1");
        // 2. Construct a key to find order number 100
        Key orderKey = new Key(new Object[] { 100 });
        // 3. Find the Orders row with the key
        Row[] ordersFound = vo.findByKey(orderKey, 1);
        if (ordersFound != null && ordersFound.length > 0) {
             Row order = ordersFound[0];
             // 4. Displays the key of the Orders row
             showKeyFor(order);
             // 5. Accesses row set of Orders using OrderItems view link accessor
             RowSet items = (RowSet)order.getAttribute("SItemView");
             // 6. Iterates over the Items row
             while (items.hasNext()) {
                 Row itemRow = items.next();
                 // 4. Displays the key of each Items row
                 showKeyFor(itemRow);
             }
        }
        Configuration.releaseRootApplicationModule(am, true);
    }
 
    private static void showKeyFor(Row r) {
       // get the key for the row passed in
       Key k = r.getKey();
       // format the key as "(val1,val2)"
       String keyAttrs = formatKeyAttributeNamesAndValues(k);
       // get the serialized string format of the key, too
       String keyStringFmt = r.getKey().toStringFormat(false);
       System.out.println("Key " + keyAttrs + " has string format " + 
                             keyStringFmt);
    }

    // Build up "(val1,val2)" string for key attributes
    private static String formatKeyAttributeNamesAndValues(Key k) {
       StringBuffer sb = new StringBuffer("(");
       int attrsInKey = k.getAttributeCount();
       for (int i = 0; i < attrsInKey; i++) {
           if (i > 0)
               sb.append(",");
               sb.append(k.getAttributeValues()[i]);
       }
       sb.append(")");
       return sb.toString();
    }
}

この例を実行すると、次の例に示す結果が生成されます。シリアライズされたキーの文字列フォーマットは16進数で、キー内のすべての属性を示す単一文字列に情報が含まれています。

Key (100) has string format 000100000003313030
Key (100,156) has string format 000200000003C2020200000002C102
Key (100,157) has string format 000200000003C2020200000002C102
...

findByKey()での部分キーの使用に関する必知事項

複数のエンティティ・オブジェクトの慣用名に基づくビュー・オブジェクトでは、部分的に移入されたキーを指定してビュー行を検索できます。部分キーは、複数属性のKeyオブジェクトで、一部の属性がnullに設定されたものです。ただし、findByKey()を実行するために使用できる部分キーの種類には、厳密な規則があります。

ビュー・オブジェクトがn個のエンティティ・オブジェクトの慣用名(n > 1)に基づいている場合、ビュー行のキーは、デフォルトで、関連するすべてのエンティティ・オブジェクトの慣用名のすべての主キー属性で構成されます。ビュー行のキーに参加する必要があるのは最初のエンティティ・オブジェクトの主キーのみですが、デフォルトですべての主キーが使用されます。

一部のセカンダリ・エンティティ・オブジェクトの慣用名のキー属性をビュー行レベルのキー属性として残す場合は、そのエンティティ・オブジェクトの主キーを構成するすべての属性をビュー行のキーの一部として残しておく必要があります。n個のエンティティ・オブジェクトの慣用名のうちのm個について(m <= n)、ビュー行の1つ以上のキー属性を残した場合、findByKey()を使用し、m個のエンティティ・オブジェクトの慣用名の任意のサブセットに基づいて行を検索できます。Keyオブジェクトで値を指定するそれぞれのエンティティ・オブジェクトの慣用名について、そのエンティティの主キーのすべての属性にNULLではない値を指定する必要があります。

ビュー・オブジェクトが1つ以上のエンティティ・オブジェクトの慣用名に基づいている場合、そのfindByKey()メソッドは、ビュー行キーでの属性がNULLではない最初のエンティティ・オブジェクトの慣用名に対応するエンティティ定義のfindByPrimaryKey()メソッドに委譲することで行を検索するため、この規則に従う必要があります。エンティティ定義のfindByPrimaryKey()メソッドでキャッシュ内のエンティティ行を検索するには、特定のエンティティ・オブジェクトに対するすべてのキー属性がNULL以外である必要があります。

具体的な例としては、OrderInfoVOビュー・オブジェクトで、OrderEOエンティティ・オブジェクトがそのプライマリ・エンティティ・オブジェクト慣用名で、AddressEOエンティティがセカンダリ参照エンティティ・オブジェクト慣用名である場合を考えてみてください。さらに、次の両方のビュー行属性のキー属性プロパティを、trueに設定したままにするものとします。

  • OrderId - OrderEOエンティティの主キー

  • AddressId - AddressEOエンティティの主キー

したがって、ビュー行のキーは、OrderIdAddressIdの組合せになります。findByKey()を呼び出すときは、次のような内容のKeyオブジェクトを渡すことができます。

  • 基礎となるOrderEOエンティティの完全に指定されたキー

    Key k = new Key(new Object[]{new Number(200), null});
    
  • 基礎となるAddressEOエンティティの完全に指定されたキー

    Key k = new Key(new Object[]{null, new Number(118)}); 
    
  • 両方のエンティティの完全に指定されたキー

    Key k = new Key(new Object[]{new Number(200), new Number(118)});
    

有効な部分キーを指定すると、findByKey()メソッドは、キー・オブジェクトで指定されていないエンティティ・オブジェクト慣用名の属性をワイルドカードとして扱い、結果として複数の行を返すことができます。

テスト・クライアントでのテスト・ユーザー認証方法

アプリケーションに対してADFセキュリティを有効にし、テスト・ユーザーにjazn-data.xmlファイルをプロビジョニングしている場合は、テスト・クライアントを実行する前に、ユーザーを認証するためのメソッド・コールを組み込む必要があります。テスト・クライアントでユーザーを認証するには、次の基本的なステップに従います(次の例を参照)。

  1. 認証サービスを作成します。

  2. jazn-data.xmlファイルに定義されている、テスト・ユーザー用のログイン資格証明を渡します。

  3. 認証が成功したら、アプリケーション・モジュールをテストします。

  4. ユーザーをログアウトします。

ADFセキュリティの構成ウィザードを実行してADFセキュリティを有効にする方法、およびJDeveloperのアイデンティティ・ストアにテスト・ユーザーを作成する方法の詳細は、「ADFセキュリティ・プロセスの概要」を参照してください。

package oracle.summit.model.test;
import oracle.jbo.ApplicationModule;
import oracle.jbo.Key;
import oracle.jbo.Row;
import oracle.jbo.RowSet;
import oracle.jbo.ViewObject;
import oracle.jbo.client.Configuration;

import oracle.adf.share.security.AuthenticationService;
import oracle.adf.share.security.authentication.AuthenticationServiceUtil;
import oracle.adf.share.ADFContext;
import oracle.adf.share.security.SecurityContext;
import oracle.adf.share.security.SecurityEnv;

import javax.security.auth.Subject;

public class TestAuthenticationClient {
    public static void main(String[] args) {
        String amDef = "test.TestAuthModule";
        String config = "TestAuthModuleLocal";

        // 1. Create authentication service.
        AuthenticationService authService =
                            AuthenticationServiceUtil.getAuthenticationService();
        try
           {
              // 2. Pass in user id and password defined in local identity store.
              authService.login("tester1", "welcome1");
           }
           catch (Exception e)
           {

           }

        // Uncomment to output authentication status
        // String userName = 
                       ADFContext.getCurrent().getSecurityContext().getUserName();

        // System.out.println("*** userName : " + userName);
        // Subject subject = 
                       ADFContext.getCurrent().getSecurityContext().getSubject();
        // System.out.println("Subject : " + subject);

        // 3. Test application module if authentication succeeds.
        if (ADFContext.getCurrent().getSecurityContext().isAuthenticated()) {
           ApplicationModule am = 
                       Configuration.createRootApplicationModule(amDef,config);
           ViewObject vo = am.findViewObject("TestView");
           // Work with your appmodule and view object here
           Configuration.releaseRootApplicationModule(am,true);

           // 4. Log out test user.
           authService.logout();

           // Uncomment to report logout success
           // boolean isAuthenticated = 
                   ADFContext.getCurrent().getSecurityContext().isAuthenticated();
           // System.out.println("*** isAuthenticated : " + isAuthenticated);
        }

    }
}