この章では、リレーショナル・マッピングの構成方法について説明します。
この章の内容は次のとおりです。
複数のマッピング・タイプに共通のTopLinkマッピング・オプションを構成する方法の詳細は、第121章「マッピングの構成」を参照してください。
TopLinkマッピングの作成方法の詳細は、第120章「マッピングの作成」を参照してください。
表28-1は、構成可能なリレーショナル・マッピング・タイプと、そのタイプで対応している構成可能オプションが記載されたタイプ別の章への相互参照を示します。
表28-1 リレーショナル・マッピングの構成
詳細は、次を参照してください。
表28-2は、複数のリレーショナル・マッピング・タイプによって共有される構成可能オプションを示します。
表28-2 共通リレーショナル・マッピング・オプション
| 構成オプション | Oracle JDeveloper | TopLink Workbench | Java | 
|---|---|---|---|
| データベース・フィールド(28.3項「データベース・フィールドの構成」を参照) |  |  |  | 
| 参照ディスクリプタ(28.4項「参照ディスクリプタの構成」を参照) |  |  |  | 
| コンテナ・ポリシー(121.14項「コンテナ・ポリシーの構成」を参照) |  |  |  | 
| メソッドまたは直接フィールド・アクセス(121.6項「マッピング・レベルでのメソッドまたは直接フィールド・アクセスの構成」を参照) |  |  |  | 
| デフォルトのNULL値(121.5項「マッピング・レベルでのデフォルトのNULL値の構成」を参照) |  |  |  | 
| 読取り専用マッピング(121.2項「読取り専用マッピングの構成」を参照) |  |  |  | 
| インダイレクション(遅延ロード)(121.3項「インダイレクション(遅延ロード)の構成」を参照) |  |  |  | 
| プライベート・リレーションシップまたは独立したリレーションシップ(121.7項「プライベート・リレーションシップまたは独立したリレーションシップの構成」を参照) |  |  |  | 
| マッピング・コメント(121.8項「マッピング・コメントの構成」を参照) |  |  |  | 
| シリアライズ・オブジェクト・コンバータ(121.9項「シリアライズ・オブジェクト・コンバータの構成」を参照) |  |  |  | 
| タイプ変換コンバータ(121.10項「タイプ変換コンバータの構成」を参照) |  |  |  | 
| オブジェクト・タイプ・コンバータ(121.11項「オブジェクト・タイプ・コンバータの構成」を参照) |  |  |  | 
| 双方向リレーションシップ(121.18項「双方向リレーションシップの構成」を参照) |  |  |  | 
| バッチ読取り(28.5項「バッチ読取りの構成」を参照) |  |  |  | 
| 問合せキー順序(28.6項「問合せキー順序の構成」を参照) |  |  |  | 
| 表およびフィールド参照(28.7項「表およびフィールド参照の構成(外部キーおよびターゲット外部キー)」を参照) |  |  |  | 
| 結合(28.8項「マッピング・レベルでの結合の構成」を参照) |  |  |  | 
オブジェクト属性をデータベース・フィールドに関連付けることができます。
表28-3では、どのリレーショナル・マッピングがこのオプションをサポートしているかを示します。
表28-3 リレーショナル・マッピングでのデータベース・フィールドのサポート
| マッピング | Oracle JDeveloperの使用方法 | TopLink Workbenchを使用したデータベース・フィールドの構成方法 | Javaの使用方法 | 
|---|---|---|---|
|  |  | 
 | 
 | 
|  |  | 
 | 
 | 
データベース・フィールドを選択する際、Javaとデータベース・フィールド・タイプの互換性を考慮する必要があります。
TopLinkは次のJavaタイプをサポートします。
java.lang: Boolean、Float、Integer、String、Double、Long、Short、Byte、Byte[ ]、Character、Character[ ]: すべてのプリミティブはこれらのクラスに関連付けられます。
java.math: BigInteger、BigDecimal
java.sql: Date、Time、Timestamp
java.util: Date、Calendar
読取りの実行中に、表28-6のマッピングは、表28-4に示す単純な一方向のデータ変換を実行します。双方向またはより複雑な変換の場合は、コンバータを使用する必要があります(27.2.2項「コンバータおよびトランスフォーマ」を参照)。
表28-3のマッピングによって、NULL値を指定することもできます。これは、プリミティブ・タイプがオブジェクトで使用され、データベース・フィールドでnull値を使用できる場合に必要となることがあります。詳細は、121.5項「マッピング・レベルでのデフォルトのNULL値の構成」を参照してください。
| Javaタイプ | データベース・タイプ | 
|---|---|
| 
 | NUMBER、NUMERIC、DECIMAL、FLOAT、DOUBLE、INT、SMALLINT、BIT、BOOLEAN | 
| 
 | BOOLEAN、BIT、SMALLINT、NUMBER、NUMERIC、DECIMAL、FLOAT、DOUBLE、INT | 
| 
 | VARCHAR、CHAR、VARCHAR2、CLOB、TEXT、LONG、LONG VARCHAR、MEMO 次のタイプはOracle9のみに適用されます。NVARCHAR2、NCLOB、NCHAR | 
| 
 | BLOB、LONG RAW、IMAGE、RAW、VARBINARY、BINARY、LONG VARBINARY | 
| 
 | TIME | 
| 
 | DATE | 
| TIMESTAMP | 
oracle.sql.TimeStampのサポート
TopLinkでは、TopLinkでOracle Database以上およびOracle9PlatformでOracle JDBCドライバを使用する場合に、Javaの日付および時間のデータ・タイプをOracle Database DATE、TIMESTAMPおよびTIMESTAMPTZデータ・タイプにマッピングするための追加サポートを提供します。
フィールドへ直接マッピングでは、フィールド値のデータベース・タイプを指定する必要はありません。TopLinkにより、適切なデータ・タイプ変換が決定されます。
表28-5は、サポートされるフィールドへ直接マッピングの組合せを示します。
表28-5 サポートされるOracleデータベースの日付および時間のフィールドへ直接マッピング
| Javaタイプ | データベース・タイプ | 説明 | 
|---|---|---|
| 
 | 
 | 完全双方向サポート。 | 
| 
 | 完全双方向サポート。 | |
| 
 | 完全双方向サポート。 | |
| 
 | 
 | 完全双方向サポート。 | 
| 
 | 完全双方向サポート。 | |
| 
 | 完全双方向サポート。 | |
| 
 | 
 | 完全双方向サポート。 | 
| 
 | 完全双方向サポート。 | |
| 
 | ナノ秒はデータベースに格納されません。 | |
| 
 | 
 | 完全双方向サポート。 | 
| 
 | 完全双方向サポート。 | |
| 
 | ミリ秒はデータベースに格納されません。 | |
| 
 | ネイティブSQLまたはバインドが、Calendarタイムゾーンを提供します。 注意: TIMESTAMPデータベース値には、タイムゾーンがありません。デフォルトでは、Calendarオブジェクトがローカルのタイムゾーンを提供します。データベースがこのタイムゾーンにない場合は、別の方法でデータベース・タイムゾーンを取得し、それに応じてCalendarオブジェクトを更新する必要があります。このため、この場合はTIMESTAMPTZの方が適しています。 | |
| 
 | ネイティブSQLまたはバインドはタイムゾーンを格納し、標準SQLはローカル・タイムゾーンに基づきます。 | |
| 
 | タイムゾーンとミリ秒はどちらも、データベースに格納されません。 | 
前述のマッピングの中には精度が損われるものもあるため、このレベルの精度を求める場合は、これらの組合せを使用しないでください。たとえば、java.sql.Date属性とTIMESTAMPTZデータベース・フィールドの間でフィールドへ直接マッピングを作成した場合、精度は損われません。しかし、java.sql.Timestamp属性とDATEデータベース・フィールドの間でフィールドへ直接マッピングを作成した場合は、属性のナノ秒またはミリ秒がデータベースに格納されません。
ダイレクト・マッピングで特定のデータベース・フィールドを選択するには、次の手順を実行します。
ナビゲータでダイレクト・マッピングの属性を選択します。そのプロパティがエディタに表示されます。
「一般」タブをクリックします。「一般」タブが表示されます。
「データベース・フィールド」フィールドを使用して、このダイレクト・マッピングのフィールドを選択します。23.2項「関連表の構成」で説明されているように、前もってディスクリプタをデータベース表に関連付けておく必要があります。
oracle.toplink.mappings.ForeignReferenceMappingの拡張であるリレーショナル・マッピングでは、属性が参照するのはその他のTopLinkディスクリプタであり、データ・ソースではありません。プロジェクトで任意のディスクリプタを選択できます。
表28-6では、どのリレーショナル・マッピングがこのオプションをサポートしているかを示します。
表28-6 リレーショナル・マッピングでの参照ディスクリプタのサポート
| マッピング | Oracle JDeveloperの使用方法 | TopLink Workbenchを使用した参照ディスクリプタの構成方法 | Javaの使用方法 | 
|---|---|---|---|
| 1対1(27.5項「1対1マッピング」を参照) |  | 
 | 
 | 
| 可変1対1(27.6項「可変1対1マッピング」を参照) |  | 
 | 
 | 
| 1対多(27.7項「1対多マッピング」を参照) |  | 
 | 
 | 
| 多対多(27.8項「多対多マッピング」を参照) |  | 
 | 
 | 
| 集約コレクション(27.9項「集約コレクション・マッピング」を参照) | 
 | 
 | 
 | 
| 集約オブジェクト(27.12項「集約オブジェクト・マッピング」を参照) |  | 
 | 
 | 
リレーショナル・マッピングに参照ディスクリプタを指定するには、次の手順を実行します。
ナビゲータでマップされた属性を選択します。そのプロパティがエディタに表示されます。
「一般」タブをクリックします。「一般」タブが表示されます。
「参照ディスクリプタ」フィールドを使用して、このリレーションシップ・マッピングで参照するディスクリプタを選択します。
| 注意:集約マッピングの場合、「参照ディスクリプタ」は集約である必要があります。詳細は、23.6項「クラスまたは集約タイプとしてのリレーショナル・ディスクリプタの構成」を参照してください。 可変1対1マッピングの場合、「参照ディスクリプタ」はインタフェースである必要があります。詳細は、第32章「リレーショナル可変1対1マッピングの構成」を参照してください。 | 
現行TopLink Workbenchプロジェクトにない参照ディスクリプタを指定できます。たとえば、現行プロジェクトにないEmployeeクラスへのマッピングを作成するには、次の手順を実行します。
現行プロジェクトにEmployeeクラスを追加します。116.2項「プロジェクトの使用」を参照してください。
Employeeディスクリプタへのリレーションシップ・マッピングを作成します。
Employeeディスクリプタを非アクティブ化します。「アクティブおよび非アクティブ・ディスクリプタ」を参照してください。
プロジェクトのデプロイXMLを生成すると、Employeeクラスへのマッピングが組み込まれますが、Employeeクラスは含まれません。
バッチ読取りは、ほとんどのリレーショナル・マッピングで使用できます。この機能は、関連するオブジェクトが常にソース・オブジェクトとともに必要であることが知られている場合のみ、使用する必要があります。
表28-7では、どのリレーショナル・マッピングがこのオプションをサポートしているかを示します。
表28-7 リレーショナル・マッピングでのバッチ読取りのサポート
| マッピング | Oracle JDeveloperの使用方法 | TopLink Workbenchを使用したバッチ読取りの構成方法 | Javaを使用したバッチ読取りの構成方法 | 
|---|---|---|---|
| 1対1(27.5項「1対1マッピング」を参照) | 
 | 
 | 
 | 
| 1対多(27.7項「1対多マッピング」を参照) | 
 | 
 | 
 | 
| 多対多(27.8項「多対多マッピング」を参照) | 
 | 
 | 
 | 
| ダイレクト・コレクション(27.10項「ダイレクト・コレクション・マッピング」を参照) | 
 | 
 | 
 | 
| ダイレクト・マップ(27.11項「ダイレクト・マップ・マッピング」を参照) | 
 | 
 | 
 | 
| 集約オブジェクト(27.12項「集約オブジェクト・マッピング」を参照) | 
 | 
 | 
 | 
リレーションシップ・マッピングでバッチ読取りを使用するには、次の手順を実行します。
ナビゲータでマップされた属性を選択します。そのプロパティがエディタに表示されます。
「一般」タブをクリックします。「一般」タブが表示されます。
このマッピングでバッチ読取りを使用することを指定するには、「バッチ読取り」オプションを選択します。
例28-1は、DescriptorCustomizerクラスを使用して、バッチ読取りをマッピングに追加する方法を示します。
例28-1 バッチを使用する問合せの最適化
public void customize(ClassDescriptor descriptor) {
    OneToManyMapping phoneNumbersMapping = new OneToManyMapping();
    phoneNumbersMapping =
        (OneToManyMapping)descriptor.getMappingForAttributeName("phones");
    phoneNumbersMapping.useBatchReading();
    // add mapping to descriptor
    descriptor.addMapping(phoneNumbersMapping);
}
問合せキー別の順序でコレクションを維持するようTopLinkを構成できます。
表28-8では、どのリレーショナル・マッピングがこのオプションをサポートしているかを示します。
表28-8 リレーショナル・マッピングでの問合せキー順序のサポート
| マッピング | Oracle JDeveloperの使用方法 | TopLink Workbenchを使用した問合せキー順序の構成方法 | Javaを使用した問合せキー順序の構成方法 | 
|---|---|---|---|
| 多対多(27.8項「多対多マッピング」を参照) | 
 | 
 | 
 | 
| 1対多(27.7項「1対多マッピング」を参照) | 
 | 
 | 
 | 
| 集約コレクション(27.9項「集約コレクション・マッピング」を参照) | 
 | 
 | 
 | 
マッピングの問合せキーの順序を指定するには、次の手順を実行します。
ナビゲータでマップされた属性を選択します。そのプロパティがエディタに表示されます。
「順序付け」タブをクリックします。「順序付け」タブが表示されます。
| フィールド | 説明 | 
|---|---|
| 問合せキー | 順序付けする問合せキーを指定します。 「追加」をクリックして問合せキーを追加するか、「削除」をクリックして順序付け操作から問合せキーを削除します。 「上へ」または「下へ」をクリックして、選択された問合せキーのソート順序を変更します。 | 
| 順序 | アルファベット順の「昇順」または「降順」のどちらで選択された問合せを順序付けするかを指定します。 | 
例28-2は、DescriptorCustomizerクラスを使用して、複雑な順序付けをマッピングに追加する方法を示します。
例28-2 問合せキー順序の構成
public void customize(ClassDescriptor descriptor) {
    OneToManyMapping phoneNumbersMapping = new OneToManyMapping();
    phoneNumbersMapping =
        (OneToManyMapping)descriptor.getMappingForAttributeName("phones");
    phoneNumbersMapping.addAscendingOrdering("areaCode");
    ExpressionBuilder phone =
        phoneNumbersMapping.getSelectionQuery().getExpressionBuilder();
    phoneNumbersMapping.getSelectionQuery().addOrdering(
        phone.get("type").toUpperCase().ascending());
    // add mapping to descriptor
    descriptor.addMapping(phoneNumbersMapping);
}
外部キーは、別の表内の一意のキー(通常は主キー)を参照する1つ以上のデータベース列の組合せです。主キーと同様、外部キーは任意の数のフィールドで、これらすべてが1つの単位として扱われます。外部キーと参照先の親キーは、フィールドの数およびタイプが同じである必要があります。
oracle.toplink.mappings.ForeignReferenceMappingの拡張であるマッピングでは、ターゲット・オブジェクトをインスタンス化できるように、外部キーを使用してデータベース内の情報を検索します。たとえば、すべてのEmployeeに属性addressがあり、この属性にAddress(独自のディスクリプタおよび表を所有)のインスタンスが含まれている場合、address属性に対する1対1マッピングにより、特定のEmployeeのAddressを見つけるための外部キー情報が指定されます。
TopLinkでは、外部キーはマッピングの2つのカテゴリ(外部キーおよびターゲット外部キー)に分類されます。
外部キーでは、キーはマッピング自体のディスクリプタに関連付けられた表にあります。たとえば、ADDRESSへのEmployee外部キーは、EMPLOYEE表内にあります。
ターゲット外部キーでは、ターゲット・オブジェクトの表からマッピングのディスクリプタの表のキーへ逆方向に参照します。たとえば、ADDRESS表は、EMPLOYEEへの外部キーを持ちます。
| 注意:マッピングを定義する前に、外部キーとターゲット外部キーの違いを完全に理解しておいてください。 | 
表参照は、外部キー参照を含むデータベース表です。
表28-9では、どのリレーショナル・マッピングがこのオプションをサポートしているかを示します。
表28-9 リレーショナル・マッピングでの表参照のサポート
| マッピング | Oracle JDeveloperの使用方法 | TopLink Workbenchを使用した表およびフィールド参照の構成方法(外部キーおよびターゲット外部キー) | Javaを使用した表およびフィールド参照の構成方法(外部キーおよびターゲット外部キー) | 
|---|---|---|---|
| 1対1(27.5項「1対1マッピング」を参照) | 
 | 
 | 
 | 
| 1対多(27.7項「1対多マッピング」を参照) | 
 | 
 | 
 | 
| 多対多(27.8項「多対多マッピング」を参照) | 
 | 
 | 
 | 
| 集約コレクション(27.9項「集約コレクション・マッピング」を参照) | 
 | 
 | 
 | 
| ダイレクト・コレクション(27.10項「ダイレクト・コレクション・マッピング」を参照) | 
 | 
 | 
 | 
| ダイレクト・マップ(27.11項「ダイレクト・マップ・マッピング」を参照) | 
 | 
 | 
 | 
TopLink Workbenchを使用して、この表をデータベースからインポートするか、または作成することができます。データベースから表をインポートする場合(5.5.1.3項「データベースからの表のインポート」を参照)、TopLinkでは、既存のデータベース制約に対応する参照を作成します(ドライバでサポートされている場合)。また、データベースで同様の制約を作成しなくても、TopLinkで参照を定義することもできます。
マッピングの参照の表を指定するには、次の手順を実行します。
ナビゲータでマップされた属性を選択します。そのプロパティがエディタに表示されます。
「表参照」タブをクリックします。「参照」タブが表示されます。
次の情報を参照し、タブのフィールド参照を選択します。
| フィールド | 説明 | 
|---|---|
| 表参照 | 既存の表を選択するか、または「新規」をクリックして新規の表参照を作成します。 | 
| 「ソース・フィールド」および「ターゲット・フィールド」 | 「追加」をクリックして、新規の外部キー参照を作成します。 既存のキー・ペア参照を削除するには、「ソース・フィールド」と「ターゲット・フィールド」を選択して「削除」をクリックします。 | 
| ソース・フィールド | この外部キー参照のソース表からデータベース・フィールドを選択します。 | 
| ターゲット・フィールド | この外部キー参照のターゲット表からデータベース・フィールドを選択します。 | 
| ターゲット外部キー | 参照がターゲット・オブジェクトの表からマッピングのディスクリプタの表のキーへの逆方向かどうかを指定します。 | 
addTargetForeignKeyFieldNameメソッドを使用し(およびターゲット外部キーのフィールド名の名前とソース表内の主キーのソースを渡し)、外部キー情報を指定します。
コンポジット・ソース主キーの場合は、主キーを構成する各フィールドに対してaddTargetForeignKeyFieldNameメソッドを使用します。
例28-3は、DescriptorCustomizerクラスを使用して、複雑な結合をマッピングに追加する方法を示します。
例28-3 マッピングへの複雑な結合の追加
public void customize(ClassDescriptor descriptor) {
    OneToManyMapping phoneNumbersMapping = new OneToManyMapping();
    phoneNumbersMapping =
        (OneToManyMapping)descriptor.getMappingForAttributeName("cellPhones");
    ExpressionBuilder phone =
        phoneNumbersMapping.getSelectionQuery().getExpressionBuilder();
    phoneNumbersMapping.addTargetForeignKeyFieldName("PHONE.EMP_ID", "EMP.ID");
    phoneNumbersMapping.getSelectionQuery(
        phone.getField("PHONE.EMP_ID").equal(phone.getParameter("EMP.ID").
        and(phone.getField("PHONE.TYPE').equal("CELL")));
    // add mapping to descriptor
    descriptor.addMapping(phoneNumbersMapping);
}
TopLinkは、ForeignReferenceMappingのマッピング・レベルでの内部結合と外部結合の構成をサポートします。マッピングを所有するクラスが読み取られる際、TopLinkランタイムは常にクラスおよびデータベース・ヒットを1つ持つ参照マッピングのターゲットを取得します。
この機能は、ターゲット・オブジェクトがソース・オブジェクトとともに常に必要な場合、またはインダイレクション(遅延ロード)が使用されない場合のみに使用します。詳細は、17.2.4項「インダイレクション(遅延ロード)」を参照してください。
また、問合せレベルで結合読取りを構成することもできます。詳細は、108.7.1.5項「結合読取りとオブジェクト・レベルの読取り問合せ」を参照してください。
Oracle JDeveloper、TopLink WorkbenchまたはJavaを使用して、マッピング・レベルで結合を構成することもできます。
結合の詳細は、110.2.7項「結合リレーションシップと複雑なリレーションシップを表す式」を参照してください。
リレーションシップ・マッピングで結合を使用するには、次の手順を実行します。
ナビゲータでマップされた属性を選択します。そのプロパティがエディタに表示されます。
「一般」タブをクリックします。「一般」タブが表示されます。
このリレーションシップで結合を使用するには、「結合の使用」オプションを選択します。
内部
外部
なし(デフォルト)
例28-4は、DescriptorCustomizerクラスを使用して、マッピング・レベルで複雑な結合を追加する方法を示します。
例28-4 マッピング・レベルでの結合の追加
public void customize(ClassDescriptor descriptor) {
    OneToManyMapping addressMapping = new OneToManyMapping();
    addressMapping =
        (OneToManyMapping)descriptor.getMappingForAttributeName("address");
    addressMapping.useJoining();
    ...
    // add mapping to descriptor
    descriptor.addMapping(addressMapping);
}