ヘッダーをスキップ
Oracle® Fusion Middleware Oracle TopLinkの理解
12c (12.1.2)
E48006-01
  ドキュメント・ライブラリへ移動
ライブラリ
製品リストへ移動
製品
目次へ移動
目次

前
 
次
 

7 マッピングの理解

EclipseLinkでは、オブジェクト表現とデータ・ソース固有の表現との間でデータのトランスフォーメーションを実行できます。このトランスフォーメーションをマッピングと呼びますが、マッピングは、EclipseLinkプロジェクトの中核をなしています。

マッピングはそれぞれ、ドメイン・オブジェクトの単一データ・メンバーに対応しています。マッピングによって、オブジェクト・データ・メンバーをそのデータ・ソース表現と関連付け、オブジェクトとデータ・ソースの間の双方向変換を実行する手段を定義します。

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

7.1 共通のマッピングの概念

この項では、EclipseLinkに固有のリレーショナル・マッピングと非リレーショナル・マッピングの概念について説明します。

7.1.1 マッピング・アーキテクチャ

マッピングを定義するには、次のコンポーネントを利用します。

  • オブジェクトのデータを格納するデータ・ソース(リレーショナル・データベース表またはスキーマ定義のXML要素など)に固有のデータ表現

  • 特定オブジェクト・クラスのディスクリプタ

  • マップするオブジェクト・クラス


注意:

マッピングは、プロジェクトの永続性の有無にかかわりなく同じです。


標準的なEclipseLinkマッピングの例については、7.1.2項「マッピングの例」を参照してください。

プロジェクトで定義するデータ・ソースのタイプによって、使用できるマッピングのタイプおよびその構成方法が決まります。永続プロジェクトでは、マッピングを使用してデータ・ソースを永続させます。永続ではないプロジェクトでは、オブジェクト形式とその他の一部のデータ表現(XMLなど)の間で単に変換を行うためにマッピングを使用します。

ディスクリプタは、特定のドメイン・オブジェクトを表し、オブジェクトのクラスを記述します。ディスクリプタは、マッピングも所有します(メモリー内で永続化または変換するクラス・データ・メンバーごとに1つのマッピング)。

ディスクリプタの詳細は、第6章「ディスクリプタの理解」を参照してください。

7.1.2 マッピングの例

EclipseLinkでは、より複雑なマッピングをサポートしますが、ほとんどのEclipseLinkのクラスは、クラスで使用可能な情報のタイプを定義する1つのデータベース表またはXML要素にマップされます。特定のクラスからインスタンス化された各オブジェクトは、一意にオブジェクトを識別する識別子(主キー)を付加して、オブジェクトの属性を構成する1つの行にマップされます。

図7-1は、最も単純なデータベース・マッピングの例を示します。

  • データベースのTable_Xは、Class_Xを表します。

  • Object_X1およびObject_X2は、Class_Xのインスタンスです。

  • Table_Xの各行は、Object_X1およびObject_X2に加えて、Class_Xのその他のインスタンスも表します。

図7-1 データベース表へのクラスおよびオブジェクトのマップ方法

図7-1の説明が続きます。
「図7-1 データベース表へのクラスおよびオブジェクトのマップ方法」の説明

EclipseLinkには、図7-1に示した単純なマッピングから複雑なマッピングまで、これらのマッピングを作成するためのツールが用意されています。

リレーショナル・マッピングのその他の例は、図7-2「シリアライズ・オブジェクト・コンバータ(リレーショナル)」を参照してください。

7.1.3 遅延ロードの使用

JPAでは、遅延ロードを、データが最初にアクセスされたときに可能であれば遅延してフェッチするという永続性プロバイダに対するヒントとして規定しています。Java EE環境でアプリケーションを開発する場合、fetchをjavax.persistence.FetchType.LAZYに設定し、必要なすべての機能を永続性プロバイダで提供します。

Java SE環境で1対1または多対1のマッピングを使用する場合、fetch属性をFetchType.LAZYに設定することで、動的ウィービングまたは静的ウィービングを使用して遅延ロードを実行します。

Java SE環境や、JVMコマンドラインで-javaagentの使用が許可されない環境で1対1または多対1のマッピングを使用する場合、fetch属性をFetchType.LAZYに設定することで、静的ウィービングを使用して遅延ロードを実行します。

表7-1は、マッピング・タイプ別の遅延ロードのサポートを示しています。

表7-1 マッピング・タイプ別の遅延ロードのサポート

マッピング Java EE Java SE

多対多

fetch属性がjavax.persistence.FetchType.LAZYに設定されている場合に遅延ロードが実行されます(デフォルト)。

fetch属性がjavax.persistence.FetchType.LAZYに設定されている場合に遅延ロードが実行されます(デフォルト)。

1対多

fetch属性がjavax.persistence.FetchType.LAZYに設定されている場合に遅延ロードが実行されます(デフォルト)。

fetch属性がjavax.persistence.FetchType.LAZYに設定されている場合に遅延ロードが実行されます(デフォルト)。

1対1

fetch属性がjavax.persistence.FetchType.LAZYに設定されている場合に遅延ロードが実行されます。

fetch属性は無視され、デフォルトのjavax.persistence.FetchType.EAGERが適用されます。

多対1

fetch属性がjavax.persistence.FetchType.LAZYに設定されている場合に遅延ロードが実行されます。

fetch属性は無視され、デフォルトのjavax.persistence.FetchType.EAGERが適用されます。

基本

fetch属性がjavax.persistence.FetchType.LAZYに設定されている場合に遅延ロードが実行されます。

fetch属性は無視され、デフォルトのjavax.persistence.FetchType.EAGERが適用されます。


7.1.4 マッピング・コンバータおよびトランスフォーマ

既存のEclipseLinkマッピングがニーズを満たしていない場合、マッピングの拡張機能を使用してカスタムのマッピングを作成できます。これらの拡張機能は、次のとおりです。


注意:

シンプル・タイプ変換以外では、データ・ソースがリレーショナルかリレーショナルでないかにかかわらず、マッピング・コンバータおよびトランスフォーマを使用できます。シンプル・タイプ変換は、XMLプロジェクトにのみ適用されます。


7.1.4.1 シリアライズ・オブジェクト・コンバータ

シリアライズ・オブジェクト・コンバータは、Javaオブジェクト・シリアライズを介して複雑なオブジェクトをバイナリ・フィールドにマップできるダイレクト・マッピングおよびダイレクト・コレクション・マッピングで使用できます。シリアライズされたオブジェクトは、通常、データベースのRAWまたはバイナリ・ラージ・オブジェクト(BLOB)フィールド、またはXML文書のHEXまたはBASE64要素に格納されます。

図7-2は、シリアライズ・オブジェクト・コンバータを使用したフィールドへ直接マッピングの例を示しています。属性jobDescriptionには、データベースのJOB_DESCフィールドに格納される、書式設定されたテキスト文書が含まれています。

図7-2 シリアライズ・オブジェクト・コンバータ(リレーショナル)

図7-2の説明が続きます
「図7-2 シリアライズ・オブジェクト・コンバータ(リレーショナル)」の説明

図7-3に、シリアライズ・オブジェクト・コンバータを使用する非リレーショナル・マッピングの例を示します。属性jobDescriptionには、EclipseLinkによってXMLスキーマのJOB DESCRIPTION要素に格納される、書式設定されたテキスト文書が含まれています。

図7-3 シリアライズ・オブジェクト・コンバータ(非リレーショナル)

図7-3の説明が続きます
「図7-3 シリアライズ・オブジェクト・コンバータ(非リレーショナル)」の説明

シリアライズ・オブジェクト・コンバータは、Javaシリアライザを利用します。ドメイン・オブジェクトをシリアライズ・オブジェクト・コンバータでマップする前に、ドメイン・オブジェクトにjava.io.Serializableインタフェースが実装され(または実装が継承され)、シリアライズされていないすべてのフィールドにtransientがマークされていることを確認してください。

7.1.4.2 タイプ変換コンバータ

タイプ変換コンバータは、複雑なオブジェクトをバイナリ・フィールドにマップできるダイレクト・マッピングおよびダイレクト・コレクション・マッピングで使用できます。たとえば、データ・ソースのNumberをJavaのStringにマップすることや、Javaのjava.util.Dateをデータ・ソースのjava.sql.Dateにマップすることができます。

図7-4に、タイプ変換マッピング(リレーショナル)の例を示します。java.util.Dateクラスは、デフォルトではTimestampとしてデータベースに格納されるため、そのクラスは、まず、java.sql.Dateのような明示的なデータベース・タイプに変換する必要があります(これはDB2に対してのみ必須であり、その他の大部分のデータベースには、任意の日付または時間を格納できる単一日付のデータ・タイプがあります)。

図7-4 タイプ変換マッピング(リレーショナル)

図7-4の説明が続きます
「図7-4 タイプ変換マッピング(リレーショナル)」の説明

図7-5は、タイプ変換マッピング(非リレーショナル)を示しています。java.util.DateオブジェクトがXMLスキーマのStringにマップされています。

図7-5 タイプ変換マッピング(非リレーショナル)

図7-5の説明が続きます
「図7-5 タイプ変換マッピング(非リレーショナル)」の説明

データベース用に特別にタイプ処理が必要な場合、タイプ変換コンバータを使用してその特定のデータベースを指定できます。コンバータには、5Kを超えるBLOBおよびCLOBフィールドの処理に必要なOracle Thin JDBCの特別な挿入および更新と同様に、NCHARNVARCHAR2およびNCLOBフィールドに必要な特別なOracle JDBCの特別なバインド・オプションのためのサポートが含まれています。

EclipseLinkは、org.eclipse.persistence.platform.database.oracleパッケージのNCharacterNClobおよびNStringタイプをコンバータのデータ・タイプとして使用し、NCHARNCLOBおよびNVARCHAR2タイプをサポートしています。EclipseLinkは、java.sql.BlobおよびClobタイプをコンバータのデータ・タイプとして使用して、5Kを超えるBLOBおよびCLOBの値をサポートしています。

データ・ソースの時間タイプ(TIMESTAMPなど)をjava.lang.Stringにマップするためにタイプ変換コンバータを構成できます。ただし、String値が次の書式に一致していることが条件です。

  • YYYY/MM/DD HH:MM:SS

  • YY/MM/DD HH:MM:SS

  • YYYY-MM-DD HH:MM:SS

  • YY-MM-DD HH:MM:SS

より複雑なStringTIMESTAMPタイプに変換する場合は、トランスフォーメーション・マッピングを検討してください(7.1.4.4項「トランスフォーメーション・マッピング」を参照)。

7.1.4.3 オブジェクト・タイプ・コンバータ

オブジェクト・タイプ・コンバータは、一定数の値をJavaオブジェクトに対応させることができるダイレクト・マッピングおよびダイレクト・コレクション・マッピングで使用できます。このコンバータは、スキーマにある値がJavaにある値と異なる場合に使用します。

図7-6は、Employee属性のgenderとXML要素のgenderとの間のオブジェクト・タイプの変換を示しています。Javaのオブジェクト属性の値がFemaleの場合、EclipseLinkではその値がFとしてXML要素に格納されます。

図7-6 オブジェクト・タイプXMLコンバータ

図7-6の説明が続きます
「図7-6 オブジェクト・タイプXMLコンバータ」の説明

7.1.4.4 トランスフォーメーション・マッピング

ある種の特殊な状況においては、データ・ソースの処理に関して、既存のマッピング・タイプおよびそのデフォルトのJavaでは、不十分な場合が考えられます。このような特殊なケースでは、Javaでの値の表現とデータ・ソースでの値の表現の間で、特殊な変換を実行するためのトランスフォーメーション・マッピングの使用を検討できます。

トランスフォーメーション・マッピングは、次の2つのコンポーネントで構成されています。

  • 属性トランスフォーマ: 読取り時にオブジェクト属性トランスフォーメーションを実行します。

  • フィールド・トランスフォーマ: 書込み時にオブジェクト属性からフィールドへのトランスフォーメーションを実行します。

トランスフォーマは、別個のクラスまたはドメイン・オブジェクトでのメソッドのいずれかとして実装できます。

属性およびフィールド・トランスフォーマの実装時には、アプリケーション・データをデータ・ソースに、またはその逆に適合させるための変換に必要な、どのような処置も講じることができます。

詳細は、7.1.5項「トランスフォーメーション・マッピング」を参照してください。

7.1.5 トランスフォーメーション・マッピング

値をJavaで表す方法とデータベースで表す方法の間の特殊な変換に、トランスフォーメーション・マッピングを使用します。


ヒント:

トランスフォーメーション・マッピングは複雑なため、多くの場合、コンバータまたはフィールドへ直接マッピングのgetterおよびsetterメソッドを使用する方が簡単に変換を実行できます。


図7-7に、トランスフォーメーション・マッピングを示します。B_DATEおよびB_TIMEフィールドからの値は、birthDate属性に格納されるjava.util.Dateの作成に使用されます。

図7-7 トランスフォーメーション・マッピング

図7-7の説明が続きます
「図7-7 トランスフォーメーション・マッピング」の説明

多くの場合、トランスフォーメーション・マッピングは、複数のフィールドの値を使用して1つのオブジェクトを作成する場合に適しています。このタイプのマッピングでは、データベースからオブジェクトを読み取る際に起動される、属性トランスフォーメーションが必要です。これには、Recordのインスタンスであるパラメータを1つ以上持たせる必要があります。属性トランスフォーメーションでは、特定の列の値の取得にRecordメソッドgetを使用できます。属性トランスフォーメーションは、オプションで2番目のパラメータ(Sessionのインスタンス)を指定できます。Sessionは、トランスフォーメーションで必要な追加の値を取得するために、データベースで問合せを実行します。トランスフォーメーションにより、属性に格納される値が返されます

トランスフォーメーション・マッピングでは、オブジェクトが保存される際にデータベースに書き込まれる、各フィールドに対するフィールド・トランスフォーメーションも必要です。トランスフォーメーションは、そのフィールドに格納される値を返します。

7.2 オブジェクト・リレーショナル・マッピングの概念

この項では、EclipseLinkに固有のリレーショナル・マッピングの概念について説明します。

7.2.1 インダイレクション(遅延ロード)

デフォルトでは、EclipseLinkは永続オブジェクトを取得する際に、そのオブジェクトが参照する従属オブジェクトをすべて取得します。リレーションシップ・マッピングによってマップされた属性に対してインダイレクション(遅延読取り、遅延ロードおよびジャストインタイム読取りとも呼びます)を構成すると、参照オブジェクトのプレースホルダとしてインダイレクション・オブジェクトが使用されます(EclipseLinkは、その特定の属性がアクセスされるまで、依存オブジェクトの読取りを遅延します)。その結果、アプリケーションにとって重要なのは取得されたオブジェクトの内容のみであり、関連オブジェクトの内容は重要でないという場合は特に、パフォーマンスが大幅に向上します。

すべての関連マッピングに対してインダイレクションを使用することをお薦めします。これにより、データ・ソースへのアクセスを最適化できるだけでなく、作業ユニット処理、キャッシュ・アクセスおよび同時実行性のEclipseLinkによる最適化が可能になります。


注意:

インダイレクションの使用は、双方向リレーションシップの適切なメンテナンスのために特に重要です。この場合、インダイレクションを使用する必要があります。コレクションを操作する場合は、透過インダイレクションを使用する必要があります(7.2.3項「透過インダイレクション」を参照)。


図7-8に、インダイレクションの例を示します。インダイレクションを使用しない場合、Orderオブジェクトを読み取ると、LineItemオブジェクトの依存コレクションも読み取られます。インダイレクションを使用する場合、Orderオブジェクトを読み取っても、LineItemオブジェクトの依存コレクションは読み取られません(lineItems属性は、インダイレクション・オブジェクトを参照します)。customerIdなどの他の属性にはアクセスできますが、EclipseLinkが依存LineItemオブジェクトを読み取るのは、lineItems属性にアクセスがあった場合のみです。

図7-8 EclipseLinkインダイレクション

図7-8の説明が続きます
「図7-8 EclipseLinkインダイレクション」の説明

EclipseLinkでは、次のインダイレクション・タイプをサポートします。

アプリケーションのシリアライズ対象となるオブジェクトにインダイレクションを使用する場合、デシリアライズ時にトリガーされないインダイレクション・オブジェクトの影響を検討する必要があります。7.2.7項「インダイレクション、シリアライズおよびデタッチ」を参照してください。

7.2.2 ValueHolderインダイレクション

インダイレクションを使用する永続クラスは、リレーションシップ属性を値ホルダー属性に置き換える必要があります。ValueHolderは、ValueHolderなど、ValueHolderInterfaceインタフェースを実装するクラスのインスタンスです。このオブジェクトには、置き換えられるオブジェクトをデータベースから取得するために必要な情報が格納されます。アプリケーションがValueHolderにアクセスしないと、置き換えられたオブジェクトはデータベースから読み取られません。

ValueHolderが置き換えるオブジェクトを取得するには、ValueHolderInterfacegetValueおよびsetValueメソッドを使用します。これらのメソッドを使用する便利な方法としては、次の例で示すように、ValueHolderInterfacegetValueおよびsetValueメソッドを、getおよびsetメソッド内で非表示にする方法があります。

図7-9に、データベースから読み取られるEmployeeオブジェクトを示します。Addressオブジェクトは読み取られず、アクセスするまで作成されません。

図7-9 読み取られないアドレス・オブジェクト

図7-9の説明が続きます
「図7-9 読み取られないアドレス・オブジェクト」の説明

図7-10に示すとおり、最初のアドレスへのアクセス時に、ValueHolderAddressオブジェクトを読み取り、それを返します。

図7-10 最初のリクエスト

図7-10の説明が続きます
「図7-10 最初のリクエスト」の説明

図7-11で示すように、アドレスに対する後続のリクエストではデータベースにアクセスしません。

図7-11 後続のリクエスト

図7-11の説明が続きます
「図7-11 後続のリクエスト」の説明

メソッド・アクセスを使用している場合、マッピングで指定されたgetおよびsetメソッドは、ValueHolderが参照しているオブジェクトではなく、ValueHolderInterfaceのインスタンスにアクセスする必要があります。アプリケーションがこれらのgetterおよびsetterを使用することはありませんが、次のようにValueHolderの使用を隠すgetterおよびsetterを使用します。

public class Employee {
 
   private ValueHolderInterface addressValueHolder;
 
   // Use this get/set pair when configuring your Mapping
   public void setAddressValueHolder(ValueHolderInterface value) {
      this.addressValueHolder = value;
   }
   public ValueHolderInterface getAddressValueHolder() {
      return this.addressValueHolder;
   }
 
   // Your application uses these methods to interact with Addresses
   public void setAddress(Address address) {
      this.addressValueHolder.setValue(address);
   }
   public Address getAddress() {
      return this.addressValueHolder.getValue(address);
   }
 
}

7.2.3 透過インダイレクション

透過インダイレクションでは、次のいずれかの関連オブジェクトのコレクションを保持する永続クラスの任意のリレーションシップ属性を宣言します。

  • java.util.Collection

  • java.util.Hastable

  • java.util.List

  • java.util.Map

  • java.util.Set

  • java.util.Vector

EclipseLinkでは、適切なインタフェースを実装し、関連オブジェクトのJust-in-Time方式による読取りも実行するインダイレクション・オブジェクトが使用されます。透過インダイレクションを使用する場合、属性をValueHolderInterfaceとして宣言する必要はありません。

新たに作成されたコレクション・マッピングは、属性がValueHolderInterfaceではない場合、デフォルトで透過的なインダイレクションを使用します。

JPAエンティティおよびPlain Old Java Object (POJO)クラスに対しては、透過インダイレクト・コンテナ・インダイレクションのウィービングが自動的に実行されるようEclipseLinkを構成できます。詳細は、3.3.1.4項「Javaバイト・コード・ウィービングの使用」および3.7項「ウィービングについて」を参照してください。

7.2.4 プロキシ・インダイレクション

JavaクラスのProxyを使用して、定義済インタフェースのプレースホルダとして動的プロキシ・オブジェクトを使用できます。特定のEclipseLinkマッピングを構成してプロキシ・インダイレクションを使用し、EclipseLinkクラスをドメイン・モデルに含めることなく、インダイレクションの利点を得ることができます。プロキシ・インダイレクションは1対1リレーションシップ・マッピングに対応し、インダイレクション・コンテナはコレクション・マッピングに対応します。

プロキシ・インダイレクションを使用するには、ドメイン・モデルが次の条件をすべて満たしている必要があります。

  • 1対1リレーションシップのターゲット・クラスがパブリック・インタフェースを実装していること

  • ソース・クラスの1対1属性が、interfaceタイプである必要があります。

  • メソッド・アクセスを使用する場合、getterメソッドおよびsetterメソッドはインタフェースを使用する必要があります。

プロキシ・インダイレクションを使用する前に、作業ユニットの使用方法で設定されている制限に注意してください(7.2.4.1項「プロキシ・インダイレクションの制限」を参照)。

プロキシ・インダイレクションを構成するため、修正メソッドでJDeveloperまたはJavaを使用できます。

7.2.4.1 プロキシ・インダイレクションの制限

Javaのプロキシ・オブジェクトは、送信されるメッセージの遮断にのみ使用できます。==instanceofまたはgetClassなどのプリミティブ操作がプロキシで使用されている場合は、メッセージは遮断されません。プロキシ・オブジェクトの使用に関しては、アプリケーションでこの制限に多少注意することが必要です。

プロキシ・インダイレクションの実装のターゲットは作業ユニットに登録できません。かわりに、先にソース・オブジェクトを作業ユニットに登録します。これにより、ソース・オブジェクト・クローンでgetterコールを使用し、ターゲット・オブジェクト・クローンを取得できます。

7.2.5 ウィービング済インダイレクション

ウィービング用に構成したJPAエンティティまたはPOJOクラスの場合、EclipseLinkでは、1対1マッピングのValueHolderインダイレクションのウィービングが実行されます。アプリケーションにコレクション・マッピング(1対多または多対多)が含まれている場合にEclipseLinkで変更追跡に対するウィービングが実行されるようにするには、すべてのコレクション・マッピングに対し、透過インダイレクト・コンテナ・インダイレクションのみが使用されるように構成する必要があります(コレクション・マッピングは、即時ロードやValueHolderインダイレクションが使用されるようには構成できません)。

詳細は、3.3.1.4項「Javaバイト・コード・ウィービングの使用」を参照してください。

7.2.6 インダイレクションおよびJPA

マッピングの注釈属性fetchlazyに設定すると、EclipseLink JPA永続性プロバイダでインダイレクションが使用されます。

デフォルトでは、1対多リレーションシップおよび多対多リレーションシップはLAZYで、透過インダイレクションが使用されます。一方、1対1リレーションシップおよび多対1リレーションシップはLAZYではありません。

1対1リレーションシップおよび多対1リレーションシップをLAZYに設定してウィービングを有効にすると、EclipseLink JPA永続性プロバイダでは、ウィービングを介して、これらのリレーションシップに対するValueHolderインダイレクションが有効になります。

詳細は、次を参照してください。

7.2.7 インダイレクション、シリアライズおよびデタッチ

インダイレクション(遅延ロード)を使用している場合、永続オブジェクトのグラフにトリガーされていないインダイレクション・オブジェクトが含まれる可能性があります。インダイレクション・オブジェクトは一時オブジェクトで、1つのJVMと別のJVMの間でシリアライズが存続することはないため、トリガーされていないインダイレクション・オブジェクトでは、デシリアライズ後にリレーションシップへのアクセスが行われるとエラーがトリガーされます。

アプリケーションでは、デシリアライズ後に必要なインダイレクト・リレーションシップがシリアライズ前にインスタンス化されていることを確認する必要があります。これを行うには、ValueHolderまたはウィービング済インダイレクションを使用して任意のリレーションシップのgetメソッドにアクセスし、透過インダイレクションを使用して任意のリレーションシップのsizeメソッドをコールします。アプリケーションで、シリアライズ時にリレーションシップを常にインスタンス化する場合、永続クラスのシリアライズwriteObjectメソッドを上書きして、最初に目的のリレーションシップをインスタンス化できます。多数のリレーションシップや階層の深いリレーションシップを持つオブジェクトでは、ラージ・オブジェクト・グラフをシリアライズしないように注意してください(クライアントで必要とされるリレーションシップのみがインスタンス化されるのが理想的です)。

JPAエンティティをシリアライズする場合、シリアライズの前にインスタンス化されていない遅延リレーションシップは、アクセスされるとエラーの原因となります。ウィービングをサーバーで使用し、エンティティをクライアントにシリアライズする場合、jarの静的ウィービングを通じて、またはEclipseLinkエージェントを使用したクライアントJVMの起動を通じて、同じウィービング・クラスがクライアントに存在している必要があります。

詳細は、3.3.1.4項「Javaバイト・コード・ウィービングの使用」を参照してください。

7.3 Object-XMLマッピングの概念

この項では、EclipseLinkに固有の非リレーショナル・マッピングの概念について説明します。

7.3.1 シンプル・タイプ変換

シンプル・タイプ変換は、ダイレクト・マッピングおよびダイレクト・コレクション・マッピングとともに使用し、XMLスキーマで定義したとおり、要素の<type>属性に基づいて、XML要素の値を適切なJavaタイプに自動的に変換できます。


注意:

シンプル・タイプ変換は、XMLプロジェクトにのみ適用されます。


コードでは、これは、次のようにXMLFieldsetIsTypedTextFieldメソッドを使用してマッピングを作成する場合に設定されます。

XMLDirectMapping mapping = new XMLDirectMapping();
XMLField tef = new XMLField();
tef.setIsTypedTextField(true);
tef.setXPath("NUMBER/text()");
mapping.setField(tef);
mapping.setAttributeName("number");
xmlDescriptor.addMapping(mapping); 

シンプル・タイプ変換は、マッピングのXPathがテキスト・ノードを指定している場合にのみ使用できます。シンプル・タイプ変換は、マッピングのXPathが属性を指定している場合は使用できません。

シンプル・タイプ変換を使用すると、XML文書の保持タイプ情報を作成できます。これは、java.lang.Integerまたはjava.util.Calendarなど、特定オブジェクト属性の場合とは異なり、java.lang.Objectおよびjava.io.Serializableなどの汎用オブジェクト属性がEclipseLinkで特定のタイプ変換をトリガーしないため、オブジェクト・モデルで汎用オブジェクト属性を指定する際に役立ちます。

図7-12は、PhoneNumberクラスのnumber属性のタイプ変換XMLマッピングを示しています。Java属性は、タイプの保持に必要な具体的な情報が不足している点に注意してください。シンプル・タイプ変換では、タイプを保持するためにタイプ情報を結果の文書に追加します。

図7-12 シンプル・タイプ変換

図7-12の説明が続きます。
「図7-12 シンプル・タイプ変換」の説明

デフォルトでは、EclipseLinkでは組込みの読取りおよび書込み変換ペアが使用されます(7.3.1.1項「デフォルトの読取り変換」および7.3.1.2項「デフォルトの書込み変換」を参照)。

独自のシンプル・タイプ変換の指定および構成によってこの動作をオーバーライドして、たとえば、XMLバイナリ・データをBase64として書き込むことができます。

7.3.1.1 デフォルトの読取り変換

表7-2は、XML要素を読み取るための、組込みの変換ペアのリストを示しています。スキーマ<type>属性が指定され、シンプル・タイプ変換が有効な場合、読み取られた値は対応するJavaタイプに変換されます。

表7-2 シンプル・タイプ変換の読取り変換

スキーマ・タイプ Javaタイプ

base64Binary

Byte[]

boolean

Boolean

byte

Byte

date

Calendar

dateTime

Calendar

double

Double

float

Float

hexBinary

Byte[]

int

int

integer

BigInteger

long

Long

short

Short

string

String

time

Calendar

unsignedByte

Short

unsignedInt

Long

unsignedShort

Integer


7.3.1.2 デフォルトの書込み変換

表7-3は、XML要素を書き込むための、組込みの変換ペアのリストを示しています。Javaクラス属性が表7-3にあるタイプで、シンプル・タイプ変換が有効である場合、書き込まれる要素に該当するスキーマ・タイプが指定されます。

表7-3 シンプル・タイプ変換の書込み変換

Javaタイプ スキーマ・タイプ

Byte[]

hexBinary

BigInteger

integer

Boolean

boolean

Byte

byte

Calendar

dateTime

GregorianCalendar

dateTime

Double

double

Float

float

Integer

int

Long

long

int

int

short

short

String

string


7.4 Object-JSONマッピングの概念

EclipseLink MOXyでは、JSON (JavaScript Object Notation)を対象とするオブジェクトの変換機能がサポートされます。この機能は、RESTfulサービスを作成する場合に便利です(JAX-RSサービスはXMLとJSON両方のメッセージを受け取ることができます)。

EclipseLinkは、次のようなJSONの読取り時と書込み時のすべてのMOXyオブジェクト/XMLオプションに対応しています。

EclipseLinkでは、JSON文書のマッピングに次のサポートが提供されます。

JSON文書に対するEclipseLinkサポートの詳細は、『Oracle Fusion Middleware Oracle TopLinkによるJAXBアプリケーションの開発』のJSON文書の使用に関する項を参照してください。

7.5 JPAマッピング・タイプについて

リレーショナル表にエンティティ・クラスをマップするには、永続フィールドごとにマッピングを構成する必要があります。次の項では、EclipeLinkのJPAマッピング・タイプについて説明します。

7.5.1 基本マッピング

シンプルJavaタイプは、エンティティの即時状態の一部としてそのフィールドまたはプロパティにマップされます。シンプルJavaタイプのマッピングは、基本マッピングと呼ばれます。

デフォルトでは、EclipseLink永続性プロバイダによって、シンプル・タイプの基本マッピングが自動的に構成されます。

次の注釈を使用して、アプリケーションでこれらのマッピングを実装する方法を調整します。

すべてのマッピング・タイプに、オプションの共通セットがあります。

  • 読取り専用: 読取りおよびコピー時にマッピングで値の移入を行うように指定します。複数のマッピングで同じデータベース列を共有する場合には必須です。

  • コンバータ: ほとんどのマッピング・タイプでカスタム・データ・タイプおよびデータの変換を使用できます。

    • 注釈: @Converter@TypeConverter@ObjectTypeConverter@StructConverter@Convert

    • 外部メタデータ: <converter><type-converter><object-type-converter><struct-converter><convert>

これらの注釈の詳細は、『Oracle Fusion Middleware Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』を参照してください。

7.5.2 デフォルトの変換およびコンバータ

EclipseLinkでは、JPA定義の注釈に加え、次のコンバータ注釈を定義します。

  • @Converter

  • @TypeConverter

  • @ObjectTypeConverter

  • @StructConverter

  • @Convert

EclipseLink永続性プロバイダは、次の順序でコンバータ注釈を検索します。

  • @Convert

  • @Enumerated

  • @Lob

  • @Temporal

  • シリアライズ(自動)

クラス、フィールドおよびプロパティ・レベルでコンバータを定義できます。次のタイプのクラスでEclipseLinkコンバータを指定できます。

  • @Entity

  • @MappedSuperclass

  • @Embeddable

次のマッピングでEclipseLinkコンバータを使用できます。

  • @Basic

  • @Id

  • @Version

  • @BasicMap

  • @BasicCollection

他のタイプのマッピング注釈を使用してコンバータを指定すると、EclipseLinkによって例外がスローされます。

これらの注釈の詳細は、『Oracle Fusion Middleware Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』を参照してください。

7.5.3 コレクション・マッピング

DescriptorCustomizerクラスを使用して、EclipseLinkディスクリプタおよびマッピングAPIを通じて追加の拡張マッピングおよびマッピング・オプションにアクセスできます。

7.5.3.1 1対多マッピング

1対多マッピングは、1つのソース・オブジェクトとターゲット・オブジェクトのコレクションの間の関連を表すために使用されます。それらは、ターゲット・オブジェクトのCollection(または他のコレクション・タイプ)によるJavaでの実装が簡単だが、リレーショナル・データベースによる実装が難しいもののよい例です。

Javaコレクションでは、所有者がその一部を参照します。リレーショナル・データベースでは、その一部がその所有者を参照します。リレーショナル・データベースでは、この実装を使用して問合せをより効率的にします。

図7-13 1対多リレーションシップ

この図は1対多リレーションシップを示しています。
「図7-13 1対多リレーションシップ」の説明


注意:

1対多リレーションシップに示されているphone属性のタイプは、Vectorです。コレクション属性の宣言にはCollectionインタフェース(またはCollectionインタフェースを実装する任意のクラス)を使用できます。


7.5.3.1.1 JPAマッピング

デフォルトで、JPAでは、1対多の多重度を持つ多値のアソシエーションに対してOneToManyマッピングを自動的に定義します。

@OneToMany注釈を使用して次の操作を行います。

  • フェッチ・タイプをEAGERに構成します。

  • 関連するターゲット・エンティティを構成します(使用されるコレクションは汎用を使用して定義されないため)。

  • アソシエーションのターゲットにカスケードする必要のある操作を構成します(たとえば、所有側エンティティが削除されると、アソシエーションのターゲットも削除されます)。

  • 単方向の1対多リレーションシップのために永続性プロバイダによって使用される結合表の詳細を構成します。mappedByまたはJoinColumnを使用する1対多では、関連オブジェクトの削除がデータベース上でカスケードされます。JoinTableを使用する1対多では、結合表の削除がデータベース上でカスケードされます(ターゲット・オブジェクトは、制約方向のためにプライベートであってもカスケードされません)。

詳細は、JPA仕様の11.1.23項「JoinTable Annotation」を参照してください。

http://jcp.org/en/jsr/detail?id=317

7.5.3.2 多対多マッピング

多対多マッピングは、ソース・オブジェクトのコレクションとターゲット・オブジェクトのコレクションの間のリレーションシップを表します。この場合、ソースとターゲットのレコード間の関連を管理するための中間表の作成が必要です。

図7-14は、Javaの多対多マッピングおよびリレーショナル・データベース表の多対多マッピングを示しています。

図7-14 多対多リレーションシップ

多対多リレーションシップ
「図7-14 多対多リレーションシップ」の説明


注意:

多対多リレーションシップに示されているプロジェクト属性では、コレクション属性を宣言するためにCollectionインタフェース(またはCollectionインタフェースを実装する任意のクラス)を使用できます。


7.5.3.2.1 JPAマッピング

デフォルトで、JPAでは、多対多の多重度を持つ多値のアソシエーションに対してManyToManyマッピングを自動的に定義します。

@ManyToMany注釈を使用して次の操作を行います。

  • フェッチ・タイプをEAGERに構成します。

  • NULL値がアプリケーションにとって不適切である場合、NULL値を禁止するようにマッピングを構成します(非プリミティブ・タイプの場合)。

  • 関連するターゲット・エンティティを構成します(使用されるコレクションは汎用を使用して定義されないため)。

  • アソシエーションのターゲットにカスケードする必要のある操作を構成します(たとえば、所有側エンティティが削除されると、アソシエーションのターゲットも削除されます)。

@ManyToMany注釈でサポートされる属性のリストは、Java Persistence仕様を参照してください。

http://jcp.org/en/jsr/detail?id=317

7.5.4 オプティミスティック・ロックの使用

オプティミスティック・ロックの使用をお薦めします。オプティミスティック・ロックを使用した場合、すべてのユーザーにデータへの読取りアクセス権限があります。ユーザーが変更を書き込もうとすると、アプリケーションにより、ユーザーがデータを読み取ってから、そのデータが変更されていないかが確認されます。

7.5.4.1 ステートレス環境でのオプティミスティック・ロック

ステートレス環境では、期限切れの(失効した)データを処理しないよう、特に注意する必要があります。失効したデータを処理しないための一般的な方法は、オプティミスティック・ロックを実装し、オプティミスティック・ロックの値をオブジェクトに格納することです。この方法は、ステートレス・アプリケーションがオブジェクトをシリアライズする場合、またはオブジェクトの内容を代替形式でクライアントに送信する場合には、十分注意して行う必要があります。これらの場合、オプティミスティック・ロックの値を編集ページのHTTPコンテンツとしてクライアントに転送します。次に、任意の書込みトランザクションの戻り値を使用して、クライアントが処理を実行しているときに、データが変更されていないことを確認する必要があります。

オプティミスティック・バージョン・ロック・ポリシーまたはオプティミスティック・フィールド・ロック・ポリシーを使用できます。バージョン・ロック・ポリシーの使用をお薦めします。

7.5.4.2 オプティミスティック・バージョン・ロック

@Version注釈を使用して、オプティミスティック・ロックの値として機能するエンティティ・クラスのバージョン・フィールドまたはプロパティを指定することで、JPA管理のオプティミスティック・ロックを有効化できます(推奨)。

バージョン・フィールドまたはプロパティを選択する場合、次の条件を満たす必要があります。

  • 1つのエンティティに対してただ1つのバージョン・フィールドまたはプロパティがあること

  • プライマリ表に永続化されたプロパティまたはフィールドを選択すること

  • アプリケーションでバージョン・プロパティまたはフィールドを変更しないこと

詳細は、JPA仕様の11.1.45項「Table Annotation」を参照してください。

http://jcp.org/en/jsr/detail?id=317


注意:

フィールドまたはプロパティ・タイプは、数値型(NumberlongintBigDecimalなど)またはjava.sql.Timestampである必要があります。EclipseLinkでは数値型の使用をお薦めします。


@Version注釈には属性はありません。@Version注釈では、EclipseLinkコンバータの使用がサポートされます。7.5.2項「デフォルトの変換およびコンバータ」を参照してください。

詳細は、JPA仕様の11.1.9項「Column Annotation」を参照してください。

http://jcp.org/en/jsr/detail?id=317