Oracle® Fusion Middleware Oracle Application Development FrameworkによるFusion Webアプリケーションの開発 12c (12.1.2) E48099-02 |
|
前 |
次 |
この章では、ADFビジネス・コンポーネントの継承を使用して、Oracle ADFアプリケーションで複数のビュー行型を公開するADFビュー・オブジェクトを作成する方法を説明します。また、この章では、エンティティ・オブジェクトの継承を使用するかわりの方法として、ビュー・オブジェクトの継承階層を定義して異種ビュー行を生成する方法についても説明します。
この章には次の項が含まれます:
ビュー・オブジェクトでは、ベース・エンティティ・オブジェクトによって表現される表を作成できます。一般に、エンティティ・ベースのビュー・オブジェクトを作成するときには、Domestics
(国内の顧客に関連する固有の属性を含むと考えられる)など、単一の型を持つエンティティ行を操作するようにビュー・オブジェクトを作成します。また、場合によっては、同じ行セットでエンティティ・オブジェクト継承階層に基づいて行を問い合せて更新することもあります。たとえば、同じ行セットで、Customers
、Domestics
およびInternationals
の各エンティティ・オブジェクトの継承階層に共通する属性を処理することがあります。このようなビュー・オブジェクトは多相ビュー・オブジェクトと呼ばれます。クライアントで多相ビュー・オブジェクトが適切に使用されるようにするために、ビュー・オブジェクトでは、異種混在の行セット内の各行について、委譲先のエンティティ・オブジェクトを認識しておく必要があります。行の型を識別するために、多相ビュー・オブジェクトは、各行の対応する表を特定する識別子属性に依存しています。
ADFビジネス・コンポーネントでは、多相ビュー・オブジェクトを作成する2つの方法をサポートしています。多相ビュー・オブジェクトを作成する方法は、次のとおりです。
多相エンティティ・オブジェクトの慣用名(ビュー・オブジェクトのエンティティ・サブタイプの継承から派生したもの)をベースにする
多相ビュー行(定義したビュー・オブジェクト階層から派生したもの)をベースにする
最初のタイプの多相ビュー・オブジェクト(エンティティ・サブタイプの継承に基づくもの)を使用する場合、クライアントにエンティティ・オブジェクト慣用名の様々なサブタイプが公開されることはありません。クライアントが関係する範囲では、ビュー・オブジェクトの結果セットの各行は同じ属性セットと同じ行の型を持ちます。このようになるのは、ADFビジネス・コンポーネントによって、識別子属性の値に基づいて必ず正しいエンティティ・オブジェクト行サブタイプが作成されるようになっているからです。つまり、多相エンティティ・オブジェクトの慣用名を使用することで、ビュー行の型は一定でありながら、ビュー行のエンティティ行の部分でのみ型が変更されるようになっています。
2番目のタイプの多相ビュー・オブジェクト(ビュー・オブジェクト階層の継承に基づくもの)では、結果に1つ以上のビュー行サブタイプを含めることができるようにアプリケーション・モジュールを構成できます。クライアントに表示されるビュー行の型に異なる複数のサブタイプを生成できるのは、多相ビュー行を使用した場合のみです。また、多相エンティティ・オブジェクトの慣用名の場合とは異なり、ビュー行のサブタイプに属性を追加してクライアントに公開できることも、多相ビュー行のみの特徴です。
注意: この項で説明する例を試すには、4.19項「ビジネス・ドメイン・レイヤーでの継承の使用」で使用したものと同じ |
どちらか一方のポリモフィズムを使用するか、2つを組み合せることができます。
通常は一緒に使用する方が役に立ちますが、ビュー行ポリモフィズム機能と多相エンティティ・オブジェクト慣用名機能は異なるものであり、個別に使用できます。特に、ビュー行ポリモフィズムの機能は、読取り専用ビュー・オブジェクトにも、エンティティ・ベースのビュー・オブジェクトにも使用できます。両方のメカニズムを組み合せると、多相のエンティティ行部分とビュー行型の両方を持つことができます。
ビュー・オブジェクトまたはエンティティ・オブジェクトでビュー行ポリモフィズムを使用するには、それぞれに個別の識別子属性プロパティを構成する必要があることに注意してください。これが必要になるのは、読取り専用ビュー・オブジェクトには、識別子情報を推測する関連エンティティ・オブジェクトの慣用名が含まれていないためです。
識別子属性が1レベルを超えない深さで定義されるビュー・オブジェクトを必要とする多相ビュー・オブジェクトの場合は、制限があります。プロジェクトで行のサブタイプを指定する識別子属性を持つ多相ビュー・オブジェクを定義する場合がありますが、このとき別のビュー・オブジェクトを使用して、最初の多相ビュー・オブジェクトに基づいてさらにサブ行を指定すると、サブ行の表示でエラーが発生します。多相ビュー・オブジェクトを作成する場合は、識別子属性の定義を1レベルに制限してください。
まとめると、ビュー行のポリモフィズムを使用する場合は、次の手順を実行します。
継承階層のルート・ビュー・オブジェクトのビュー・オブジェクト・レベルで、識別子にする属性を構成します。
継承されるビュー・オブジェクトの階層を定義し、階層内の各ビュー・オブジェクトのビュー・オブジェクト・レベルの識別子属性に、サブタイプ値プロパティとして個別値(ビュー・オブジェクト定義ファイルの属性のDefaultValue
として識別される)を指定します。
アプリケーション・モジュールのサブタイプのリストに、この階層内にあるサブクラス化されたビュー・オブジェクトのリストを入れます。
一方、多相エンティティ・オブジェクトの慣用名を含むビュー・オブジェクトを作成するには、次のことを行います。
継承階層のルート・エンティティ・オブジェクトのエンティティ・オブジェクト・レベルで、識別子にする属性を構成します。
継承されるエンティティ・オブジェクトの階層を定義し、階層内のエンティティ・オブジェクトのそれぞれでオーバーライドを行って、そのエンティティ・オブジェクト・レベルの識別子属性のサブタイプ値プロパティに個別の値を設定します。
ビュー・オブジェクトのサブタイプのリストに、サブクラス化されたエンティティ・オブジェクトのリストを入れます。
多相エンティティ・オブジェクトの慣用名とは、継承階層のベース・エンティティ・オブジェクトを参照し、そのエンティティのサブタイプも処理するように構成されているものです。図7-1は、多相エンティティ・オブジェクトの慣用名でビュー・オブジェクトを使用した結果を示しています。エンティティ・ベースのCustomerList
ビュー・オブジェクトには、プライマリ・エンティティ・オブジェクトの慣用名としてCustomers
エンティティ・オブジェクトがあります。ビュー・オブジェクトは、データベースから取得された各行を、Customers
の様々なサブタイプに固有の属性を持つエンティティ行に分割します。識別子属性の値の検査に基づいて、適切なエンティティ行サブタイプを作成します。たとえば、CustomerList
の問合せで、国内企業ABC Company
の1行と国際企業Simms Athletic
の1行が取得された場合、基礎になっているエンティティ行は図で示されているようになります。
多相エンティティ・オブジェクトの慣用名で作成するビュー・オブジェクトは、ベース・エンティティ・オブジェクトおよびサブタイプ・エンティティの1つ以上の属性を継承できます。エンティティ・オブジェクトから選択する属性は、ビュー・オブジェクト属性定義によってオーバーライドされます。エンティティ・ベースのビュー・オブジェクトが識別子属性を持つエンティティ・オブジェクトを参照していると、JDeveloperはその識別子属性も(主キー属性に加えて)問合せに含まれるようにします。
始める前に:
多相ビュー・タイプに関する知識が役立つ場合があります。詳細は、7.1項「多相ビュー・オブジェクトについて」を参照してください。
次のタスクを完了する必要があります。
4.2.2項「エンティティの作成ウィザードで単一のエンティティ・オブジェクトを作成する方法」の説明に従って、多相エンティティ・オブジェクトの慣用名の継承元ベース・エンティティ・オブジェクトを作成します。
4.10.14項「エンティティ・オブジェクト継承階層の識別子属性の設定方法」の説明に従って、ベース・エンティティ・オブジェクトを拡張して、多相エンティティ・オブジェクトの慣用名を作成し、エンティティ行サブタイプの基礎となる識別子属性を指定します。
ベース・エンティティ・オブジェクトからエンティティ・ベースのビュー・オブジェクトを作成し、各多相エンティティ・オブジェクトの慣用名に対して作成するサブタイプ・ビュー・オブジェクトに共通する属性を選択します。ベース・ビュー・オブジェクトは、サブタイプ・ビュー・オブジェクトを作成するために使用されます。エンティティ・ベースのビュー・オブジェクトの作成の詳細は、5.2.1項「エンティティ・ベースのビュー・オブジェクトの作成方法」を参照してください。
多相エンティティ・オブジェクトの慣用名でビュー・オブジェクトを作成するには:
「アプリケーション」ウィンドウでデータ・モデル・プロジェクトを右クリックし、「新規」、「ビュー・オブジェクト」の順に選択します。
ビュー・オブジェクトの作成ウィザードで、ビュー・オブジェクトの名前を指定し、「拡張」フィールドの横にある「参照」をクリックします。
たとえば、Domestics
とInternationals
の各サブタイプ・エンティティ・オブジェクトの多相エンティティ・オブジェクト慣用名を使用したビュー・オブジェクト作成をサポートするために、データ・モデル・プロジェクトでベースのCustomers
エンティティ・オブジェクトを定義できます。各多相エンティティ・オブジェクト慣用名のビュー・オブジェクトを作成するときには、DomesticList
とInternationalList
などの名前でビュー・オブジェクトを作成できます。
「親の選択」ダイアログで、ベース・エンティティ・オブジェクトから作成したエンティティ・ベースのビュー・オブジェクトを選択して、「OK」をクリックします。
たとえば、サブタイプ・エンティティ・オブジェクトDomestics
に対するビュー・オブジェクトDomesticList
を作成する場合は、拡張するビュー・オブジェクトとして、TheCustomer
を選択します。
ビュー・オブジェクト作成ウィザードで「次」をクリックして、「選択済」リストにベース・エンティティ・オブジェクトがすでに表示され、Extendedとラベルが付けられていることを確認します(図7-2を参照)。
「エンティティ・オブジェクト」ページの「使用可能」リストで、ベース・エンティティ・オブジェクトから作成したエンティティ・サブタイプを探して、「OK」をクリックします。
たとえば、ベース・エンティティ・オブジェクトCustomers
に対するビュー・オブジェクトDomesticList
を作成する場合は、エンティティ・サブタイプとしてDomestics
を選択します。
「ビジネス・コンポーネント」ダイアログで、「OK」をクリックしてビュー・オブジェクトのエンティティ・オブジェクトの慣用名をオーバーライドします。
ビジネス・コンポーネント」ダイアログで、ベース・エンティティ・オブジェクトの慣用名の属性をエンティティ・サブタイプでオーバーライドする旨の警告が示されます(図7-3を参照)。
「選択済」リストで、オーバーライドされたエンティティ・オブジェクトを選択して、「サブタイプ」をクリックします。
「サブタイプの選択」ダイアログで、目的のエンティティ・サブタイプを「選択済」から選択し、「OK」をクリックします。
たとえば、DomesticList
ビュー・オブジェクト用にエンティティ・サブタイプDomestics
を選択します(図7-4を参照)。
ビュー・オブジェクトの作成ウィザードの「エンティティ・オブジェクト」ページで、「次へ」をクリックし、ウィザードの「属性」ページで必要な属性をエンティティ・サブタイプから「選択済」リストに移動します。
たとえば、DomesticList
ビュー・オブジェクト用に、エンティティ・サブタイプDomestics
からState
属性を選択します(図7-5を参照)。
ウィザードへの入力を完了させて、「終了」をクリックします。
概要エディタの「エンティティ・オブジェクト」ページに、選択されたエンティティ・オブジェクトとエンティティ・サブタイプ・オーバーライドが表示されます。たとえば、DomesticList
ビュー・オブジェクトの概要エディタに、Customers (Domestics): overridden
のように、オーバーライドされたエンティティ・オブジェクトとカッコで囲まれたサブタイプが表示されます(図7-6を参照)。
この手順を繰り返して、ベース・エンティティ・オブジェクトに作成した追加の多相エンティティ・オブジェクトの慣用名のビュー・オブジェクトを作成します。
多相エンティティ・オブジェクトの慣用名でエンティティ・ベースのビュー・オブジェクトを作成すると、JDeveloperにより、許可されるエンティティ・サブタイプに関する情報がビュー・オブジェクトのXMLドキュメントに追加されます。たとえば、前述のDomesticList
ビュー・オブジェクトを作成すると、許可されるサブタイプ・エンティティ・オブジェクトの名前が次のようなAttrArrayタグに記録されます。
<ViewObject Name="DomesticList" ... > <EntityUsage Name="TheCustomer" Entity="oracle.summit.model.polymorphicsample.Customers" > </EntityUsage> ... <AttrArray Name="EntityImports"> <Item Value="oracle.summit.model.polymorphicsample.Domestics" /> <Item Value="oracle.summit.model.polymorphicsample.Internationals" /> </AttrArray> <!-- etc. --> </ViewObject>
多相エンティティ・オブジェクトの慣用名を使用する場合は、識別子属性による問合せのフィルタリングによって期待するサブタイプのみが含まれるように、次のベスト・プラクティスに従うことをお薦めします。
ビュー・オブジェクトが階層で使用可能なエンティティ・サブタイプのサブセットのみを使用する場合は、識別子列が期待するエンティティ・タイプと一致する行のみを返すように問合せを制限する適切なWHERE
句を含める必要があります。問合せでサブタイプのフィルタリングを行うときには、識別子属性のみに依存しないでください。問合せを絞り込むための属性を追加しないと、ビュー・オブジェクトでは事実上すべての行に問合せが実行され、どの識別子の値にも一致しない列がクライアントで破棄されることになります。
設計上、クライアントはエンティティ・オブジェクトを直接使用しません。かわりに、当面のタスクに関連する情報のセットを表す適切なビュー・オブジェクトのビュー行を通して、間接的にエンティティ・オブジェクトを使用します。ビュー・オブジェクトは、当面のタスクに関連する1つまたは複数のエンティティ・オブジェクトの基礎となる属性の特定のセットを公開できるのと同じように、これらのエンティティから選択されたメソッドのセットも公開できます。そのためには、カスタム・ビュー行のJavaクラスを有効にし、次のビュー行クラスでメソッドを記述します。
ビュー行で生成されるエンティティ・アクセッサを使用して基礎となる適切なエンティティ行にアクセス
そのメソッドの呼出し
たとえば、Customers
エンティティ・オブジェクトに、そのCustomersImpl
クラスのperformCustomerFeature()
メソッドが含まれているとします。このメソッドをCustomerList
ビュー行でクライアントに公開するには、カスタム・ビュー行のJavaクラスを有効にし、例7-1で示されているメソッドを記述します。JDeveloperは、エンティティ・オブジェクトの慣用名の別名に基づいて、関係する各エンティティ・オブジェクトの慣用名に対するビュー行クラスで、エンティティ・アクセッサ・メソッドを生成します。CustomerList
ビュー・オブジェクトでのCustomers
エンティティの別名はTheCustomer
であるため、そのエンティティ・オブジェクトの慣用名に関係するエンティティ行部分を返すためのgetTheCustomer()
メソッドを生成します。
例7-1 選択したエンティティ・オブジェクト・メソッドの委譲によるビュー行での公開
// In CustomerListRowImpl.java public void performCustomerFeature() { getTheCustomer().performCustomerFeature(); }
ビュー行のperformCustomerFeature()
メソッドのコードでは、このgetTheCustomer()
メソッドを使用して基礎となるCustomersImpl
エンティティ行クラスにアクセスし、そのperformCustomerFeature()
メソッドを呼び出します。このコーディング・スタイルは委譲と呼ばれるもので、ビュー行メソッドはそのメソッドの1つの実装を、基礎となるエンティティ・オブジェクトの対応するメソッドに委譲します。多相エンティティ・オブジェクトの慣用名のあるビュー行で委譲が使用されると、委譲されたメソッド呼出しは、基礎となる適切なエンティティ行サブタイプによって処理されます。つまり、CustomersImpl
クラス、DomesticsImpl
クラスおよびInternationalsImpl
クラスが異なる方法でperformCustomerFeature()
メソッドを実装している場合は、現在行のエンティティ・サブタイプに応じて、適切な実装が使用されます。
クライアント行インタフェースでこのメソッドを公開すると、クライアント・プログラムは、カスタム行インタフェースを使用して、特定のビュー行でカスタム・ビジネス機能を呼び出すことができます。例7-2は、TestEntityPolymorphism
クラスのコード行を示しています。CustomerList
ビュー・オブジェクト・インスタンスのすべての行を反復し、各行をカスタムのCustomerListRow
インタフェースにキャストして、performCustomerFeature()
メソッドを呼び出しています。
例7-2 エンティティ・オブジェクトに委譲するビュー行メソッドの呼出し
CustomerList customerlist = (CustomerList)am.findViewObject("CustomerList"); customerlist.executeQuery(); while (customerlist.hasNext()) { CustomerListRow customer = (CustomerListRow)customerlist.next(); System.out.print(customer.getEmail()+"->"); customer.performCustomerFeature(); }
例7-2のクライアント・コードを実行すると、次のような出力が生成されます。
austin->## performCustomerFeature as Domestics hbaer->## performCustomerFeature as Internationals : sking->## performCustomerFeature as Domestic :
Customers
エンティティに関連する行では、CustomersImpl
クラスのperformCustomerFeature()
メソッドが使用されたことを確認するメッセージが表示されます。Domestics
エンティティに関連する行とInternationals
エンティティに関連する行では異なるメッセージが表示され、DomesticsImpl
クラスとInternationalsImpl
クラスが継承されたperformCustomerFeature()
メソッドに関して持っている異なる実装がはっきり示されます。
多相エンティティ・オブジェクトの慣用名のあるビュー・オブジェクトでは、新しいビュー行を作成すると、それにはベース・エンティティ・オブジェクトの慣用名と一致する型を持つ新しいエンティティ行部分が含まれます。かわりにいずれかのエンティティ・サブタイプで新しいビュー行を作成するには、createAndInitRow()
メソッドを使用します。例7-3は、CustomerList
ビュー・オブジェクトのJavaクラスにおける2つのカスタム・メソッドを示しています。これらのメソッドでは、createAndInitRow()
を使用して、クライアントがDomestics
またはInternationals
サブタイプのエンティティ行を持つ新しい行を作成できるようにしています。createAndInitRow()
を使用するには、例で示されているように、NameValuePairs
オブジェクトのインスタンスを作成し、それに識別子属性の適切な値を設定します。次に、そのNameValuePairs
をcreateAndInitRow()
メソッドに渡し、指定した識別子属性の値に基づいて、適切なエンティティ行サブタイプを持つ新しいビュー行を作成します。
例7-3 エンティティ・サブタイプを持つ新しい行を作成するためのカスタム・メソッドの公開
// In CustomerListImpl.java public CustomerListRow createCustomersRow() { NameValuePairs nvp = new NameValuePairs(); nvp.setAttribute("CustomerTypeCode","DOMESTIC"); return (CustomerListRow)createAndInitRow(nvp); } public CustomerListRow createInternationalsRow() { NameValuePairs nvp = new NameValuePairs(); nvp.setAttribute("CustomerTypeCode","INTERNATIONAL"); return (CusotmersListRow)createAndInitRow(nvp); }
このようなメソッドをビュー・オブジェクトのカスタム・インタフェースで公開すると、実行時に、クライアントはそれを呼び出して、適切なエンティティ・サブタイプを持つ新しいビュー行を作成できます。例7-4は、TestEntityPolymorphism
クラスのこの機能に関連する行を示しています。最初に、createRow()
メソッド、createDomesticsRow()
メソッドおよびcreateInternationalsRow()
メソッドを使用して、3つの新しいビュー行を作成します。次に、新しい行のそれぞれで、CustomerListRow
カスタム・インタフェースからperformCustomerFeature()
メソッドを呼び出します。
各行は期待したとおりに関連するエンティティ行のサブタイプに固有の方法でメソッドを処理し、結果を生成します。
## performCustomerFeature as Customer ## performCustomerFeature as Domestic ## performCustomerFeature as International
例7-4 異なるエンティティ・サブタイプでの新しいビュー行の作成
// In TestEntityPolymorphism.java CustomerListRow newCustomer = (CustomerListRow)CustomerList.createRow(); CustomerListRow newDomestic = Customerlist.createDomesticsRow(); CustomerListRow newInternational = Customerlist.createInternationalsRow(); newCustomer.performCustomerFeature(); newDomestic.performCustomerFeature(); newInternational.performCustomerFeature();
7.2項「多相エンティティ・オブジェクトの慣用名での作業」で示されている例では、「舞台裏」であるエンティティ・オブジェクト・レベルでポリモフィズムが発生していました。クライアント・コードは同じCustomerListRow
インタフェースを使用してすべてのビュー行を処理するので、Domestics
エンティティ・オブジェクトに基づく行と、Customers
エンティティ・オブジェクトに基づく行を区別することはできません。コードは、基礎となるエンティティ・サブタイプのすべての型に共通するビュー行属性とメソッドの同じセットを使用して、すべてのビュー行を処理します。
多相ビュー行をサポートするようにビュー・オブジェクトを構成すると、クライアントは、行の型に固有のビュー行インタフェースを使用して、異なる型のビュー行を処理できます。このようにすると、クライアントは、必要に応じて、特定のサブタイプに固有のビュー属性にアクセスしたり、ビュー行メソッドを呼び出したりできます。図7-7は、前述のCustomerList
の例に対してこの機能を有効にするビュー・オブジェクトの階層を示しています。DomesticList
とInternationalList
は、ベース(または親)のCustomerList
ビュー・オブジェクトを拡張した子ビュー・オブジェクトです。それぞれが、エンティティ・オブジェクトの慣用名として保持する、Customers
のそのサブタイプに固有の追加属性を含んでいることに注意してください。DomesticList
にはState
追加属性が含まれ、InternationalList
にはState
属性はないものの、Language
属性が含まれています。ビュー行ポリモフィズム用に構成されている場合、クライアントは次のものを使用してCustomerList
ビュー・オブジェクトの結果を処理できます。
顧客に関係するビュー行のCustomerListRow
インタフェース
国内顧客に関係するビュー行のDomesticListRow
インタフェース
国際顧客に関係するビュー行のInternationalListRow
インタフェース
これにより、クライアントは、特定のサブタイプのビュー行に固有の追加属性とビュー行メソッドにアクセスできます。
多相ビュー行によって作成するビュー・オブジェクトは、それぞれに固有のベース・エンティティ・オブジェクトを持つビュー・オブジェクトの階層から、1つ以上の属性を継承できます。拡張されたビュー・オブジェクトから選択する属性は、親ビュー・オブジェクトの多相ビュー行定義によってオーバーライドされます。エンティティ・ベースのビュー・オブジェクトが識別子属性を持つエンティティ・オブジェクトを参照していると、JDeveloperはその識別子属性も(主キー属性に加えて)問合せに含まれるようにします。
始める前に:
多相ビュー・タイプに関する知識が役立つ場合があります。詳細は、7.3項「多相ビュー行関連の作業」を参照してください。
多相ビュー行を持つビュー・オブジェクトを作成するには:
「アプリケーション」ウィンドウで、ベース・ビュー・オブジェクトにするビュー・オブジェクトをダブルクリックします。
たとえば、図7-7では、CustomerList
ビュー・オブジェクトがベース・ビュー・オブジェクトになっています。
概要エディタで「属性」ナビゲーション・タブをクリックし、ビュー行の識別子属性を選択して、「詳細」タブをクリックします。
「詳細」ページで、識別子属性にデフォルト値を指定し、「多相識別子」チェック・ボックスを選択して、使用するビュー行インタフェースを識別するものとして属性をマークします。
ベース・ビュー・オブジェクトのビュー行インタフェースが使用するものと予想される属性値に一致する値を、「サブタイプ値」フィールドで指定する必要があります。たとえば、CustomerList
ビュー・オブジェクトでは、CustomerTypeCode
属性を識別子属性としてマークし、デフォルトのサブタイプ値をCUSTOMER
にします。
ベース・ビュー・オブジェクトのカスタム・ビュー行クラスを有効にし、少なくとも1つのメソッドをクライアント行インタフェースで公開します。このメソッドとしては、ビュー行属性アクセッサ・メソッドの1つまたは全部、および任意のカスタム・ビュー行メソッドを使用できます。
ベース・ビュー・オブジェクトを拡張する新しいビュー・オブジェクトを作成します。
たとえば、図7-7では、DomesticList
がベースのCustomerList
ビュー・オブジェクトを拡張しています。
拡張されたビュー・オブジェクトのカスタム・ビュー行クラスを有効にします。
妥当な場合は、新しいカスタム・ビュー行メソッドを追加するか、または親ビュー・オブジェクトの行クラスから継承するカスタム・ビュー行メソッドをオーバーライドします。
拡張されたビュー・オブジェクトの識別子属性に個別の値を設定します。
DomesticList
ビュー・オブジェクトは、CustomerTypeCode
識別子属性にDOMESTIC
という値を設定しています。
必要に応じて、手順5から7を繰り返し、他の拡張されたビュー・オブジェクトを追加します。
たとえば、InternationalList
は、CustomerList
を拡張する2番目のビュー・オブジェクトです。このオブジェクトでは、CustomerTypeCode
識別子属性に値INTERNATIONAL
を設定しています。
ビュー・オブジェクトの階層を設定した後、ビュー行ポリモフィズムに参加するビュー・オブジェクト・サブタイプのリストを定義する必要があります。これは次のようにして行います。
階層内のビュー・オブジェクトの各型のインスタンスを、アプリケーション・モジュールのデータ・モデルに追加します。
たとえば、CustomersModule
アプリケーション・モジュールには、CustomerList
、DomesticList
およびInternationalList
の各ビュー・オブジェクトのインスタンスがあります。
アプリケーション・モジュールの概要エディタで「データ・モデル」ナビゲーション・タブをクリックし、「サブタイプ」ボタンをクリックします。
表示される「サブタイプ」ダイアログで、ビュー行ポリモフィズムに加えるビュー・オブジェクト・サブタイプを「使用可能」から「選択済」リストに移動し、「OK」をクリックします。
多相ビュー行を操作する場合は、行の型を扱って、表示する属性をカスタマイズするか、ビュー行のエンティティ・サブタイプに固有のメソッドに委譲を行うことができます。
拡張されたビュー・オブジェクトを作成すると、そのオブジェクトは親のエンティティ・オブジェクトの慣用名を継承します。親のビュー・オブジェクトのエンティティ・オブジェクトの慣用名がドメイン・レイヤーのサブタイプを持つエンティティ・オブジェクトに基づいている場合は、継承した親のエンティティ・オブジェクトの慣用名型ではなく、これらのサブタイプのいずれかを拡張されたビュー・オブジェクトが使用するようにする場合があります。このようにするには2つの理由があります。
エンティティ・サブタイプに固有の属性を選択するため
エンティティ・サブタイプに固有のメソッドに委譲するビュー行メソッドを作成できるようにするため
これを行うには、継承されたエンティティ・オブジェクトの慣用名をオーバーライドして、目的のエンティティ・サブタイプを参照する必要があります。そのためには、拡張されたビュー・オブジェクトの概要エディタで次の手順を行います。
ビュー・オブジェクトのエンティティ・オブジェクト慣用名をオーバーライドするには:
「アプリケーション」ウィンドウで、オーバーライドするエンティティ・オブジェクトの慣用名を含むビュー・オブジェクトをダブルクリックします。
概要エディタで「エンティティ・オブジェクト」ナビゲーション・タブをクリックして、拡張されたエンティティ・オブジェクトの慣用名を使用していることを確認します。
たとえば、DomesticList
ビュー・オブジェクトを拡張するDomesticList
ビュー・オブジェクトを作成するときは、最初、「選択済」リストに、TheCustomer
という別名を使用するエンティティ・オブジェクトの慣用名が「TheCustomer(Customers): 拡張済」のように表示されます。エンティティ・オブジェクトの慣用名の型はカッコ内で示され、「拡張済」というラベルはエンティティ・オブジェクトの慣用名が現在は親から継承されていることを示します。
「使用可能」リストで、継承されたものをオーバーライドする目的のエンティティ・サブタイプを選択します。既存のエンティティ・オブジェクトの慣用名型のサブタイプ・エンティティである必要があります。
たとえば、Customers
エンティティ型に基づいて継承されたエンティティ・オブジェクトの慣用名をオーバーライドするには、「使用可能」リストでDomestics
エンティティ・オブジェクトを選択します。
「>」をクリックして、「選択済」リストに移動します。
表示される警告に応答し、既存の継承されたエンティティ・オブジェクトの慣用名をオーバーライドすることを確認します。
この手順を実行すると、「選択済」リストが更新されて、オーバーライドされたエンティティ・オブジェクトの慣用名を反映するようになります。たとえば、DomesticList
ビュー・オブジェクトの場合は、Customers
ベースのエンティティ・オブジェクトの慣用名をDomestics
エンティティ・サブタイプでオーバーライドすると、表示が「TheCustomer (Domestics): オーバーライド済」に更新されます。
エンティティ・オブジェクトの慣用名をエンティティ・サブタイプに関係するようにオーバーライドした後は、エディタの「属性」タブを使用して、そのサブタイプに固有の追加属性を選択できます。たとえば、DomesticsList
ビュー・オブジェクトには、Domestics
エンティティ・オブジェクトに固有の、State
という名前の追加属性が含まれます。
拡張されたビュー・オブジェクトのエンティティ・オブジェクトの慣用名をサブタイプ・エンティティを参照するようにオーバーライドした後は、サブタイプ・エンティティ・クラスに固有のメソッドに委譲するビュー行メソッドを作成できます。例7-5は、InternationalList
ビュー・オブジェクトに対するカスタム・ビュー行クラスのperformInternationalFeature()
メソッドのコードを示しています。getTheCustomer()
エンティティ行アクセッサからの戻り値をサブタイプInternationalsImpl
にキャストした後、Internationals
エンティティ・オブジェクトに固有のperformInternationalFeature()
メソッドをコールしています。
例7-5 サブタイプ・エンティティのメソッドに委譲するビュー行メソッド
// In InternationalListRowImpl.java public void performInternationalFeature() { InternationalsImpl international = (InternationalsImpl)getTheCustomer(); international.performInternationalFeature(); }
注意: JDeveloperでは、 |
例7-6は、次の手順を実行するTestViewRowPolymorphism
クラスのコード行を示しています。
CustomerList
ビュー・オブジェクトの行を反復処理します。
ループでは、各行について、Javaのinstanceof
演算子を使用して、現在の行がDomesticListRow
またはInternationalListRow
のインスタンスかどうかを検査しています。
行がDomesticListRow
の場合は、行をこのさらに具体的な型にキャストした後、次の処理を行います。
DomesticListRow
インタフェースに固有のperformDomesticFeature()
メソッドをコールします。
DomesticList
ビュー・オブジェクトに固有のState
属性の値にアクセスします。
行がInternationalListRow
の場合は、行をこのさらに具体的な型にキャストした後、次の処理を行います。
InternationalListRow
インタフェースに固有のperformInternationalFeature()
メソッドをコールします。
InternationalList
ビュー・オブジェクトに固有のLanguage
属性の値にアクセスします。
それ以外の場合は、CustomerListRow
でメソッドをコールします。
例7-6 クライアント・コードでのビュー行ポリモフィズムの使用
// In TestViewRowPolymorphism.java ViewObject vo = am.findViewObject("CustomerList"); vo.executeQuery(); // 1. Iterate over the rows in the CustomerList view object while (vo.hasNext()) { CustomerListRow Customer = (CustomerListRow)vo.next(); System.out.print(Customer.getEmail()+"->"); if (Customer instanceof DomesticListRow) { // 2. If the row is a DomesticListRow, cast it DomesticListRow mgr = (DomesticListRow)Customer; mgr.performDomesticFeature(); System.out.println("State: "+domestic.getState()); } else if (Customer instanceof InternationalListRow) { // 3. If the row is an InternationalListRow, cast it InternationalListRow international = (InternationalListRow)Customer; international.performInternationalFeature(); System.out.println("Speaks English: "+international.getLanguage()); } else { // 4. Otherwise, just call a method on the CustomerListRow Customer.performCustomerFeature(); } }
例7-6のコードを実行すると、次のような出力が生成されます。
daustin->## performInternationalFeature called English spoken: Yes hbaer->## performCustomerFeature as Customer : sking->## performDomesticFeature called State: CA :
これは、ビュー行ポリモフィズムの機能を使用することで、クライアントが異なる型のビュー行を区別し、ビュー行の各サブタイプに固有のメソッドと属性にアクセスできたことを示します。