この章では、リレーショナル・ディスクリプタの構成方法について説明します。
詳細は、次を参照してください。
表26-1に、リレーショナル・ディスクリプタに構成可能なデフォルトのオプションを示します。
表26-1に、リレーショナル・ディスクリプタに構成可能なデフォルトのオプションを示します。
表26-1 リレーショナル・ディスクリプタの構成可能オプション
オプション | タイプ | TopLink Workbench |
Java |
---|---|---|---|
|
基本 |
![]() |
![]() |
|
基本 |
![]() |
![]() |
|
基本 |
![]() |
![]() |
|
詳細 |
![]() |
![]() |
|
詳細 |
![]() |
![]() |
|
詳細 |
![]() |
![]() |
|
詳細 |
![]() |
![]() |
基本 |
![]() |
![]() |
|
|
詳細 |
![]() |
![]() |
|
詳細 |
![]() |
![]() |
|
詳細 |
![]() |
![]() |
|
詳細 |
![]() |
![]() |
|
詳細 |
![]() |
![]() |
|
詳細 |
|
|
|
詳細 |
![]() |
![]() |
「ディスクリプタ・レベルでのキャッシュ・タイプとサイズの構成」 |
詳細 |
![]() |
![]() |
|
詳細 |
|
|
「ディスクリプタ・レベルでのキャッシュ・コーディネーションの変更伝播機能の構成」 |
詳細 |
|
|
|
詳細 |
|
|
|
詳細 |
|
|
|
詳細 |
![]() |
![]() |
「クラスまたは集約タイプとしてのリレーショナル・ディスクリプタの構成」 |
詳細 |
![]() |
![]() |
|
詳細 |
![]() |
![]() |
「子(ブランチまたはリーフ)クラス・ディスクリプタに関する継承の構成」 |
詳細 |
|
|
|
詳細 |
![]() |
![]() |
|
詳細 |
![]() |
![]() |
|
詳細 |
|
|
|
詳細 |
![]() |
![]() |
「イベント・ハンドラとしてのドメイン・オブジェクト・メソッドの構成」 |
詳細 |
|
|
「イベント・ハンドラとしてのディスクリプタ・イベント・リスナーの構成」 |
詳細 |
|
|
|
詳細 |
![]() |
![]() |
|
詳細 |
![]() |
![]() |
|
詳細 |
![]() |
![]() |
|
詳細 |
![]() |
![]() |
|
詳細 |
|
|
|
詳細 |
![]() |
![]() |
|
詳細 |
![]() |
![]() |
|
詳細 |
|
|
|
詳細 |
![]() |
|
|
基本 |
![]() |
![]() |
各リレーショナル・クラス・ディスクリプタ(「リレーショナル・クラス・ディスクリプタ」を参照)は、そのクラスのインスタンスを格納するためのデータベース表に関連付ける必要があります。これは、リレーショナル集約ディスクリプタには当てはまりません(「リレーショナル集約ディスクリプタ」を参照)。
データベース表にディスクリプタを関連付けるには、次の手順を実行します。
「関連表」のリストから、ディスクリプタに関連付けるデータベース表を選択します。ディスクリプタとデータベース表の関連付けは、主キーを指定する前に行う必要があります。
Javaを使用してディスクリプタの関連表を構成するには、RelationalDescriptor
のメソッドsetTableName
またはaddTableName
を使用します。
順序付けを使用すると、オブジェクトの挿入時に、そのオブジェクトの主キーまたはIDを自動的に割り当てることができます。
TopLinkの順序付け機能をプロジェクト・レベル(「プロジェクト・レベルでの順序付けの構成」を参照)またはセッション・レベル(「セッション・レベルでの順序付けの構成」を参照)で構成することによって、順序値を取得する方法、つまり使用する順序タイプをTopLinkに指示します。
順序付けを有効化するには、ディスクリプタ・レベルでTopLinkの順序付けを構成し、ディスクリプタの参照クラスのインスタンスが作成される際に順序値を書き込む表および列をTopLinkに指示します。
順序フィールドと順序名が構成されたディスクリプタにのみ、順序番号が割り当てられます。
順序フィールドとは、順序番号が割り当てられるデータベース・フィールドで、ほとんどの場合、主キー・フィールドがこれになります(「主キーの構成」を参照)。順序名とは、そのディスクリプタに使用する順序の名前です。順序名の意味は、次に示すとおり、使用する順序付けのタイプによって異なります。
表による順序付けを使用する場合、順序名は順序を格納する行のSEQ_NAMEの値を参照します。
Oracleのネイティブ順序付けを使用する場合、順序名はデータベース内に作成されているOracle順序オブジェクトを参照します。他のデータベースのネイティブ順序付けを使用する場合、順序名はそれ自体としては意味を持ちませんが、互換性確保のため必ず設定してください。
順序名には、プロジェクトに定義するカスタムの順序名を参照させることもできます。
詳細は、「リレーショナル・プロジェクトにおける順序付けの概要」を参照してください。
ディスクリプタに順序付けを構成するには、次の手順を実行します。
次の情報を参照し、順序付けの各オプションを指定します。
フィールド | 説明 |
---|---|
順序付けの使用 | このディスクリプタに順序付けを使用する場合に選択します。このオプションを選択した場合は、順序付けの「名前」、「表」および「フィールド」に値を指定します。 |
名前 | 順序の名前を指定します。
|
表 | このディスクリプタの参照クラスの新規インスタンスが作成される際にTopLinkによって順序値が書き込まれるフィールド(「フィールド」を参照)のあるデータベース表の名前を指定します。通常は、ディスクリプタのプライマリ表の名前です。 |
フィールド | このディスクリプタの参照クラスの新規インスタンスが作成される際にTopLinkで順序値を書き込むように指定した表(「表」を参照)の、フィールドの名前を指定します。通常、このフィールドには参照クラスの主キーを指定します(「主キーの構成」を参照)。
|
Javaを使用すると、様々なディスクリプタに対して、タイプの異なる複数の順序を使用した順序付けを構成できます。セッションのログイン・オブジェクトに順序オブジェクトを構成し、その順序オブジェクトをディスクリプタから名前によって参照します。ディスクリプタの順序名は、セッションのログイン・オブジェクトに登録された順序オブジェクト名を参照します。
次に示す各例は、セッションに例26-1の順序が構成されていることを前提としています。
例26-1 順序の例
dbLogin.addSequence(new TableSequence("EMP_SEQ", 25)); dbLogin.addSequence(new DefaultSequence("PHONE_SEQ", 30)); dbLogin.addSequence(new UnaryTableSequence("ADD_SEQ", 55)); dbLogin.addSequence(new NativeSequence("NAT_SEQ", 10));
Javaコードを使用すると、次の順序構成を行えます。
例26-2のように、順序名を使用して順序とディスクリプタを関連付けます。順序EMP_SEQ
は、例26-1でこのプロジェクトのログイン・オブジェクトに追加済です。Employee
クラスの新規インスタンスが作成されると、TopLinkランタイムではEMP_SEQ
という順序(この例ではTableSequence
)を使用してEMP_ID
フィールドの値が取得されます。
例26-3のように、複数のディスクリプタに同一の順序を関連付けることができます。この例では、Employee
ディスクリプタとPhone
ディスクリプタが同一のNativeSequence
を使用しています。複数のディスクリプタに同一の順序を共有させると、事前割当てのパフォーマンスが向上します。事前割当ての詳細は、「順序付けと事前割当てサイズ」を参照してください。
例26-4では、存在しない順序(NEW_SEQ
)をディスクリプタに関連付けています。例26-1でこのプロジェクトのログインにNEW_SEQ
という順序を追加していないため、TopLinkランタイムでこのディスクリプタ用にNEW_SEQ
というDefaultSequence
が作成されます。DefaultSequence
の詳細は、「デフォルトの順序付け」を参照してください。
TopLinkを使用して、基本的な永続データ操作(挿入、更新、削除、読取り、すべて読取り、存在チェック)ごとに1つのSQL問合せを定義できます。これにより、リレーショナル・マップ・オブジェクトに問い合せてそれを変更する際に、TopLinkランタイムではデフォルトのSQL問合せのかわりに適切なSQL問合せが使用されます。
SQL文字列には、引数および、ディスクリプタがマップする任意のフィールドを含めることができます。SQL文字列に引数を指定するには、#<arg-name>
の形式で次のように入力します。
select * from EMP where EMP_ID = #EMP_ID
挿入および更新用のSQL文字列は、ディスクリプタがマップする任意のフィールドを引数としてとることができます。
読取り、削除および存在チェック用のSQL文字列は、主キー・フィールドのみを引数としてとることができます。
すべて読取り用のSQL文字列は、クラスの全インスタンスを返す必要があるため、引数をとることはできません。
TopLink Workbenchを使用すると、挿入、更新、削除、読取り、すべて読取り用のカスタムSQL文字列を定義できます(「TopLink Workbenchの使用」を参照)。
Javaを使用した場合には、挿入、更新、削除、読取り、すべて読取り、存在チェック用に、カスタムSQL文字列またはCall
オブジェクトを定義できます(「Javaの使用」を参照)。Call
を使用すると、より複雑なSQL文字列の定義や、カスタムのストアド・プロシージャの起動ができます。
CMPプロジェクトの場合は、問合せリストはejb-jar.xml
ファイルに格納されます。問合せは、このファイル内で定義してからTopLink Workbenchに読み取ることも(「ejb-jar.xmlファイルからの読取り」を参照)、「問合せ」タブで定義してからこのファイルに書き込むこともできます(「ejb-jar.xmlファイルへの書込み」を参照)。
注意: オプティミスティック・ロック(「ロック・ポリシーの構成」を参照)を使用するアプリケーションの永続データ更新操作をカスタマイズする際には、最初のオブジェクトの読取り後に行のバージョン・フィールドが変更された場合に、カスタム更新文字列がそのオブジェクトを書き込まないようにする必要があります。さらに、オブジェクトを正常に書き込んだ場合は、バージョン・フィールドを増分する必要があります。例: update Employee set F_NAME = #F_NAME, VERSION = VERSION + 1 where (EMP_ID = #EMP_ID) AND (VERSION = #VERSION) また、更新文字列はデータベースの行カウントを維持する必要があります。 |
基本的な永続データ操作のカスタムSQL問合せを構成するには、次の手順を実行します。
適切なSQL関数タブをクリックして、ディスクリプタに対するこれらのアクションを制御するための独自のSQLを入力します。次の情報を参照し、タブに指定を行います。
DescriptorQueryManager
では、次の永続データ操作用のデフォルトSQLが生成されます。
挿入
更新
削除
読取り
すべて読取り
存在チェック
Javaコードにより、ディスクリプタ問合せマネージャを使用して、これらの関数をクラス単位で実行するためのカスタムSQL文字列を提供できます。
そのためには、ClassDescriptor
メソッドgetQueryManager
を使用してDescriptorQueryManager
を取得し、表26-2に示すDescriptorQueryManager
の各メソッドを使用します。
表26-2 カスタムSQLを構成するためのディスクリプタ問合せマネージャ・メソッド
デフォルトSQLを変更する対象操作 | 使用するディスクリプタ問合せマネージャ・メソッド |
---|---|
挿入 |
|
|
|
|
|
更新 |
|
|
|
|
|
削除 |
|
|
|
|
|
読取り |
|
|
|
|
|
すべて読取り |
|
|
|
|
|
存在チェック |
|
|
|
|
例26-5は、修正メソッドを実装し、カスタムSQL文字列を使用するようにディスクリプタ問合せマネージャを構成する方法を示しています。また、別の方法には、SQLCall
を使用して、入力、出力および入出力パラメータやパラメータ・タイプなどの機能を使用して複雑なSQL文字列を指定する方法もあります(「SQLコールの使用」を参照)。
例26-5 カスタムSQL文字列を使用したディスクリプタ問合せマネージャの構成
public static void addToDescriptor(ClassDescriptor descriptor) { // Read-object by primary key procedure descriptor.getQueryManager().setReadObjectSQLString( "select * from EMP where EMP_ID = #EMP_ID" ); // Read-all instances procedure descriptor.getQueryManager().setReadAllSQLString( "select * from EMP" ); // Insert procedure descriptor.getQueryManager().setInsertSQLString( "insert into EMP (EMP_ID, F_NAME, L_NAME, MGR_ID) values (#EMP_ID, #F_NAME, #L_NAME, #MGR_ID)" ); // Update procedure descriptor.getQueryManager().setUpdateSQLString( "update EMP set (F_NAME, L_NAME, MGR_ID) values (#F_NAME, #L_NAME, #MGR_ID) where EMP_ID = #EMP_ID" ); }
例26-6は、修正メソッドを実装し、StoredProcedureCall
(「StoredProcedureCallの使用」を参照)によってOracleストアド・プロシージャを使用するようにディスクリプタ問合せマネージャを構成する方法を示しています。この例では、結果セットを返すために出力カーソルを使用しています(「カーソルとストリームの問合せ結果の処理」を参照)。
例26-6 カスタムのストアド・プロシージャ・コールを使用したディスクリプタ問合せマネージャの構成
public static void addToDescriptor(ClassDescriptor descriptor) { // Read-object by primary key procedure StoredProcedureCall readCall = new StoredProcedureCall(); readCall.setProcedureName("READ_EMP"); readCall.addNamedArgument("P_EMP_ID", "EMP_ID"); readCall.useNamedCursorOutputAsResultSet("RESULT_CURSOR"); descriptor.getQueryManager().setReadObjectCall(readCall); // Read-all instances procedure StoredProcedureCall readAllCall = new StoredProcedureCall(); readAllCall.setProcedureName("READ_ALL_EMP"); readAllCall.useNamedCursorOutputAsResultSet("RESULT_CURSOR"); descriptor.getQueryManager().setReadAllCall(readAllCall ); // Insert procedure StoredProcedureCall insertCall = new StoredProcedureCall(); insertCall.setProcedureName("INSERT_EMP"); insertCall.addNamedArgument("P_EMP_ID", "EMP_ID"); insertCall.addNamedArgument("P_F_NAME", "F_NAME"); insertCall.addNamedArgument("P_L_NAME", "L_NAME"); insertCall.addNamedArgument("P_MGR_ID", "MGR_ID"); descriptor.getQueryManager().setInsertCall(insertCall); // Update procedure StoredProcedureCall updateCall = new StoredProcedureCall(); updateCall.setProcedureName("UPDATE_EMP"); updateCall.addNamedArgument("P_EMP_ID", "EMP_ID"); updateCall.addNamedArgument("P_F_NAME", "F_NAME"); updateCall.addNamedArgument("P_L_NAME", "L_NAME"); updateCall.addNamedArgument("P_MGR_ID", "MGR_ID"); descriptor.getQueryManager().setUpdateCall(updateCall); }
インタフェース・エイリアスを使用すると、インタフェースを介して実装クラスのかわりにディスクリプタを参照できます。この方法は、クラスにパブリック・インタフェースがあり、アプリケーションがそのパブリック・インタフェースを介してクラスを参照する必要がある場合に便利です。インタフェース・エイリアスを指定することにより、TopLinkセッションで実行される任意の問合せで、実装クラスを使用するかわりにインタフェースを参照クラスとして使用できます。
この項では、インタフェース・エイリアスの構成方法について説明します。インタフェースはTopLink Workbenchでは作成できません。インタフェース・エイリアスを構成するには、JavaパッケージまたはクラスをTopLink Workbenchプロジェクトに追加しておく必要があります。
「インタフェース・エイリアス」タブを使用して、ディスクリプタのエイリアスを指定します。各ディスクリプタに指定できるインタフェース・エイリアスは1つです。これらのインタフェースは、問合せやリレーションシップ・マッピングに使用します。
注意: インタフェース・エイリアスを使用する場合、インタフェースにはインタフェース・ディスクリプタを関連付けないでください。 |
インタフェース・エイリアスを指定するには、次の手順を実行します。
ナビゲータで、ディスクリプタを選択します。
そのディスクリプタに対して「インタフェース・エイリアス」アドバンスト・プロパティが表示されない場合は、ディスクリプタを右クリックして、コンテキスト・メニューまたは「選択」メニューから「アドバンスト・プロパティの選択」→「インタフェース・エイリアス」を選択します。
「インタフェース・エイリアス」フィールドで、「参照」をクリックしてインタフェースを選択します。
Javaを使用してインタフェース・エイリアスをディスクリプタに構成するには、例26-7のように、ディスクリプタ修正メソッドを作成して(「修正メソッドの構成」を参照)、InterfacePolicy
メソッドaddParentInterface
を使用します。
デフォルトでは、リレーショナル・プロジェクトにJavaクラスを追加するときに(「プロジェクト・クラスパスの構成」を参照)、TopLink WorkbenchによってそのJavaクラス用のリレーショナル・クラス・ディスクリプタが作成されます。クラス・ディスクリプタは、任意の永続オブジェクトに適用できます。ただし、集約リレーションシップにおいて相手オブジェクトに所有されているオブジェクトは除きます。この種のオブジェクトは、集約ディスクリプタを使用して記述する必要があります。クラス・ディスクリプタを使用すると、集約コレクションおよび集約オブジェクト・マッピングを除く任意のリレーショナル・マッピングを構成できます。
集約オブジェクトは、それを所有するオブジェクトに完全に依存するオブジェクトです。集約ディスクリプタでは、表や主キー、または多くの標準のディスクリプタ・オプションは定義しません。これらは、集約ディスクリプタが所有側のディスクリプタから取得するためです。集約マッピングを構成して、ターゲット・オブジェクト内のデータ・メンバーをソース・オブジェクトの基礎となるデータベース表のフィールドを関連付ける場合は(第41章「リレーショナル集約コレクション・マッピングの構成」および第43章「リレーショナル集約オブジェクト・マッピングの構成」を参照)、ターゲット・オブジェクトのディスクリプタを集約として指定する必要があります。
あるいは、リレーショナル・ディスクリプタから集約指定を削除して、デフォルトのタイプに返すこともできます。
集約として定義されたディスクリプタ(「子(ブランチまたはリーフ)クラス・ディスクリプタに関する継承の構成」を参照)で継承を構成できますが、その場合は継承ツリー内のすべてのディスクリプタが集約である必要があります。集約ディスクリプタとクラス・ディスクリプタは、同じ継承ツリーに置くことはできません。詳細は、「集約およびコンポジット・ディスクリプタと継承」を参照してください。
また、集約として構成したディスクリプタにはEJB情報を構成できません(「EJB情報によるディスクリプタの構成」を参照)。
詳細は、「ディスクリプタと集約」を参照してください。
リレーショナル・ディスクリプタをクラスまたは集約として構成するには、次の手順を実行します。
ナビゲータで、リレーショナル・ディスクリプタを選択します。
マッピング・ツールバーの「クラス」または「集約」ボタンをクリックします。
または、ディスクリプタを選択してメニューから「選択」→「ディスクリプタ・タイプ」→「クラス」または「集約」を選択するか、ナビゲータ・ウィンドウでディスクリプタを右クリックしてコンテキスト・メニューから「ディスクリプタ・タイプ」→「クラス」または「集約」と選択することもできます。
「集約」を選択した場合は、集約ディスクリプタの各属性を「フィールドへ直接マッピング」として指定します。詳細は、第35章「リレーショナル・フィールドへ直接マッピングの構成」を参照してください。
ターゲット・クラスの属性は、集約オブジェクト・マッピングを構成するまではデータ・ソースに直接マップされませんが、マッピング・タイプをターゲット・クラスのディスクリプタに指定することはできます。これは、ソース・オブジェクトのディスクリプタへの集約マッピングの構成時に使用するマッピング・タイプをTopLinkに指示するものです。詳細は、「リレーショナル・プロジェクトでの集約ディスクリプタとコンポジット・ディスクリプタ」を参照してください。
ディスクリプタでは、マッピングで複数の表を使用できます。複数の表は、次のいずれかの条件が満たされる場合に使用します。
サブクラスが継承に含まれ、そのスーパークラスが1つの表にマップされている一方で、そのサブクラスが別の表にマップされている追加属性を持つ場合
クラスが継承に含まれておらず、そのデータが複数の表にまたがっている場合
ディスクリプタに複数の表を指定した場合は、プライマリ表の行を他のすべての表に結合できる必要があります。デフォルトでは、TopLinkは、最初の表つまりプライマリ表の主キーがその他の表に含まれ、このため、他の表を結合できるものと想定しています。また、TopLinkでは表を結合するためのカスタム・メソッドもサポートされています。複数の表の主キー・フィールドの名前が異なる場合は、外部キーを使用して表を結合できます。使用できるのは、プライマリ表からセカンダリ表への外部キー、セカンダリ表からプライマリ表への外部キー、または2つのセカンダリ表間での外部キーです(「TopLink Workbenchの使用」を参照)。
複数表の関係が複雑な場合は、さらに複雑な結合式が必要なことがあります。たとえば、結合でタイプのコードのチェックも必要な場合や、外部結合を使用する場合などです。TopLinkでは、そのような場合に複数表結合式を使用できます(「Javaの使用」を参照)。
TopLink Workbenchでは、「複数表の情報」タブを使用して、1つのディスクリプタに複数の表を定義できます。
1つのディスクリプタに複数の表を関連付けるには、次の手順を実行します。
ナビゲータで、ディスクリプタを選択します。
ディスクリプタの「複数表の情報」アドバンスト・プロパティが表示されない場合は、ディスクリプタを右クリックして、コンテキスト・メニューまたは「選択」メニューから「アドバンスト・プロパティの選択」→「複数表の情報」を選択します。
次の情報を参照し、タブの各フィールドにデータを入力します。
フィールド | 説明 |
---|---|
プライマリ表 | このディスクリプタのプライマリ表です。このフィールドは表示専用です。 |
追加の表 | 「追加」と「削除」を使用して、追加の表を追加または削除できます。 |
プライマリ表への関連付け | 追加の表のそれぞれを次のどの方法でプライマリ表に関連付けるかを指定します。
|
参照による表の関連付け
表への関連付けで「参照」を選択すると、追加のオプションがアクティブになります。選択する参照は、プライマリ表の適切なフィールドと選択した表の主キーとを関連付けるものである必要があります。
「表参照」を選択して、プライマリ表の主キーと選択した表の主キーとの関連付け方法を定義します。「追加」をクリックして、主キーの関連付けを追加します。
Javaを使用してディスクリプタに複数表の情報を構成するには、次のClassDescriptor
メソッドを使用します。
addTable
Name
addMultipleTableForeignKeyFieldName
複雑な複数表結合式を指定するには、ディスクリプタ修正メソッドを作成し(「修正メソッドの構成」を参照)、そのメソッドに、DescriptorQueryManager
メソッドsetMultipleTableJoinExpression
を使用した結合式を追加します。詳細は、「その他の結合式の追加」を参照してください。