EclipseLinkでは、オブジェクト表現とデータ・ソース固有の表現との間でデータのトランスフォーメーションを実行できます。このトランスフォーメーションをマッピングと呼びますが、マッピングは、EclipseLinkプロジェクトの中核をなしています。
マッピングはそれぞれ、ドメイン・オブジェクトの単一データ・メンバーに対応しています。マッピングによって、オブジェクト・データ・メンバーをそのデータ・ソース表現と関連付け、オブジェクトとデータ・ソースの間の双方向変換を実行する手段を定義します。
この章の内容は次のとおりです。
この項では、EclipseLinkに固有のリレーショナル・マッピングと非リレーショナル・マッピングの概念について説明します。
マッピングを定義するには、次のコンポーネントを利用します。
オブジェクトのデータを格納するデータ・ソース(リレーショナル・データベース表またはスキーマ定義のXML要素など)に固有のデータ表現
特定オブジェクト・クラスのディスクリプタ
マップするオブジェクト・クラス
注意: マッピングは、プロジェクトの永続性の有無にかかわりなく同じです。 |
標準的なEclipseLinkマッピングの例については、7.1.2項「マッピングの例」を参照してください。
プロジェクトで定義するデータ・ソースのタイプによって、使用できるマッピングのタイプおよびその構成方法が決まります。永続プロジェクトでは、マッピングを使用してデータ・ソースを永続させます。永続ではないプロジェクトでは、オブジェクト形式とその他の一部のデータ表現(XMLなど)の間で単に変換を行うためにマッピングを使用します。
ディスクリプタは、特定のドメイン・オブジェクトを表し、オブジェクトのクラスを記述します。ディスクリプタは、マッピングも所有します(メモリー内で永続化または変換するクラス・データ・メンバーごとに1つのマッピング)。
ディスクリプタの詳細は、第6章「ディスクリプタの理解」を参照してください。
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のその他のインスタンスも表します。
EclipseLinkには、図7-1に示した単純なマッピングから複雑なマッピングまで、これらのマッピングを作成するためのツールが用意されています。
リレーショナル・マッピングのその他の例は、図7-2「シリアライズ・オブジェクト・コンバータ(リレーショナル)」を参照してください。
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 |
---|---|---|
多対多 |
|
|
1対多 |
|
|
1対1 |
|
|
多対1 |
|
|
基本 |
|
|
既存のEclipseLinkマッピングがニーズを満たしていない場合、マッピングの拡張機能を使用してカスタムのマッピングを作成できます。これらの拡張機能は、次のとおりです。
注意: シンプル・タイプ変換以外では、データ・ソースがリレーショナルかリレーショナルでないかにかかわらず、マッピング・コンバータおよびトランスフォーマを使用できます。シンプル・タイプ変換は、XMLプロジェクトにのみ適用されます。 |
シリアライズ・オブジェクト・コンバータは、Javaオブジェクト・シリアライズを介して複雑なオブジェクトをバイナリ・フィールドにマップできるダイレクト・マッピングおよびダイレクト・コレクション・マッピングで使用できます。シリアライズされたオブジェクトは、通常、データベースのRAW
またはバイナリ・ラージ・オブジェクト(BLOB
)フィールド、またはXML文書のHEX
またはBASE64
要素に格納されます。
図7-2は、シリアライズ・オブジェクト・コンバータを使用したフィールドへ直接マッピングの例を示しています。属性jobDescription
には、データベースのJOB_DESC
フィールドに格納される、書式設定されたテキスト文書が含まれています。
図7-3に、シリアライズ・オブジェクト・コンバータを使用する非リレーショナル・マッピングの例を示します。属性jobDescription
には、EclipseLinkによってXMLスキーマのJOB DESCRIPTION
要素に格納される、書式設定されたテキスト文書が含まれています。
シリアライズ・オブジェクト・コンバータは、Javaシリアライザを利用します。ドメイン・オブジェクトをシリアライズ・オブジェクト・コンバータでマップする前に、ドメイン・オブジェクトにjava.io.Serializable
インタフェースが実装され(または実装が継承され)、シリアライズされていないすべてのフィールドにtransientがマークされていることを確認してください。
タイプ変換コンバータは、複雑なオブジェクトをバイナリ・フィールドにマップできるダイレクト・マッピングおよびダイレクト・コレクション・マッピングで使用できます。たとえば、データ・ソースのNumber
をJavaのString
にマップすることや、Javaのjava.util.Date
をデータ・ソースのjava.sql.Date
にマップすることができます。
図7-4に、タイプ変換マッピング(リレーショナル)の例を示します。java.util.Date
クラスは、デフォルトではTimestamp
としてデータベースに格納されるため、そのクラスは、まず、java.sql.Date
のような明示的なデータベース・タイプに変換する必要があります(これはDB2に対してのみ必須であり、その他の大部分のデータベースには、任意の日付または時間を格納できる単一日付のデータ・タイプがあります)。
図7-5は、タイプ変換マッピング(非リレーショナル)を示しています。java.util.Date
オブジェクトがXMLスキーマのStringにマップされています。
データベース用に特別にタイプ処理が必要な場合、タイプ変換コンバータを使用してその特定のデータベースを指定できます。コンバータには、5Kを超えるBLOB
およびCLOB
フィールドの処理に必要なOracle Thin JDBCの特別な挿入および更新と同様に、NCHAR
、NVARCHAR2
およびNCLOB
フィールドに必要な特別なOracle JDBCの特別なバインド・オプションのためのサポートが含まれています。
EclipseLinkは、org.eclipse.persistence.platform.database.oracle
パッケージのNCharacter
、NClob
およびNString
タイプをコンバータのデータ・タイプとして使用し、NCHAR
、NCLOB
および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
より複雑なString
をTIMESTAMP
タイプに変換する場合は、トランスフォーメーション・マッピングを検討してください(7.1.4.4項「トランスフォーメーション・マッピング」を参照)。
オブジェクト・タイプ・コンバータは、一定数の値をJavaオブジェクトに対応させることができるダイレクト・マッピングおよびダイレクト・コレクション・マッピングで使用できます。このコンバータは、スキーマにある値がJavaにある値と異なる場合に使用します。
図7-6は、Employee
属性のgender
とXML要素のgender
との間のオブジェクト・タイプの変換を示しています。Javaのオブジェクト属性の値がFemale
の場合、EclipseLinkではその値がF
としてXML要素に格納されます。
ある種の特殊な状況においては、データ・ソースの処理に関して、既存のマッピング・タイプおよびそのデフォルトのJavaでは、不十分な場合が考えられます。このような特殊なケースでは、Javaでの値の表現とデータ・ソースでの値の表現の間で、特殊な変換を実行するためのトランスフォーメーション・マッピングの使用を検討できます。
トランスフォーメーション・マッピングは、次の2つのコンポーネントで構成されています。
属性トランスフォーマ: 読取り時にオブジェクト属性トランスフォーメーションを実行します。
フィールド・トランスフォーマ: 書込み時にオブジェクト属性からフィールドへのトランスフォーメーションを実行します。
トランスフォーマは、別個のクラスまたはドメイン・オブジェクトでのメソッドのいずれかとして実装できます。
属性およびフィールド・トランスフォーマの実装時には、アプリケーション・データをデータ・ソースに、またはその逆に適合させるための変換に必要な、どのような処置も講じることができます。
詳細は、7.1.5項「トランスフォーメーション・マッピング」を参照してください。
値をJavaで表す方法とデータベースで表す方法の間の特殊な変換に、トランスフォーメーション・マッピングを使用します。
ヒント: トランスフォーメーション・マッピングは複雑なため、多くの場合、コンバータまたはフィールドへ直接マッピングのgetterおよびsetterメソッドを使用する方が簡単に変換を実行できます。 |
図7-7に、トランスフォーメーション・マッピングを示します。B_DATE
およびB_TIME
フィールドからの値は、birthDate
属性に格納されるjava.util.Date
の作成に使用されます。
多くの場合、トランスフォーメーション・マッピングは、複数のフィールドの値を使用して1つのオブジェクトを作成する場合に適しています。このタイプのマッピングでは、データベースからオブジェクトを読み取る際に起動される、属性トランスフォーメーションが必要です。これには、Record
のインスタンスであるパラメータを1つ以上持たせる必要があります。属性トランスフォーメーションでは、特定の列の値の取得にRecord
メソッドget
を使用できます。属性トランスフォーメーションは、オプションで2番目のパラメータ(Session
のインスタンス)を指定できます。Session
は、トランスフォーメーションで必要な追加の値を取得するために、データベースで問合せを実行します。トランスフォーメーションにより、属性に格納される値が返されます。
トランスフォーメーション・マッピングでは、オブジェクトが保存される際にデータベースに書き込まれる、各フィールドに対するフィールド・トランスフォーメーションも必要です。トランスフォーメーションは、そのフィールドに格納される値を返します。
この項では、EclipseLinkに固有のリレーショナル・マッピングの概念について説明します。
デフォルトでは、EclipseLinkは永続オブジェクトを取得する際に、そのオブジェクトが参照する従属オブジェクトをすべて取得します。リレーションシップ・マッピングによってマップされた属性に対してインダイレクション(遅延読取り、遅延ロードおよびジャストインタイム読取りとも呼びます)を構成すると、参照オブジェクトのプレースホルダとしてインダイレクション・オブジェクトが使用されます(EclipseLinkは、その特定の属性がアクセスされるまで、依存オブジェクトの読取りを遅延します)。その結果、アプリケーションにとって重要なのは取得されたオブジェクトの内容のみであり、関連オブジェクトの内容は重要でないという場合は特に、パフォーマンスが大幅に向上します。
すべての関連マッピングに対してインダイレクションを使用することをお薦めします。これにより、データ・ソースへのアクセスを最適化できるだけでなく、作業ユニット処理、キャッシュ・アクセスおよび同時実行性のEclipseLinkによる最適化が可能になります。
注意: インダイレクションの使用は、双方向リレーションシップの適切なメンテナンスのために特に重要です。この場合、インダイレクションを使用する必要があります。コレクションを操作する場合は、透過インダイレクションを使用する必要があります(7.2.3項「透過インダイレクション」を参照)。 |
図7-8に、インダイレクションの例を示します。インダイレクションを使用しない場合、Order
オブジェクトを読み取ると、LineItem
オブジェクトの依存コレクションも読み取られます。インダイレクションを使用する場合、Order
オブジェクトを読み取っても、LineItem
オブジェクトの依存コレクションは読み取られません(lineItems
属性は、インダイレクション・オブジェクトを参照します)。customerId
などの他の属性にはアクセスできますが、EclipseLinkが依存LineItem
オブジェクトを読み取るのは、lineItems
属性にアクセスがあった場合のみです。
EclipseLinkでは、次のインダイレクション・タイプをサポートします。
アプリケーションのシリアライズ対象となるオブジェクトにインダイレクションを使用する場合、デシリアライズ時にトリガーされないインダイレクション・オブジェクトの影響を検討する必要があります。7.2.7項「インダイレクション、シリアライズおよびデタッチ」を参照してください。
インダイレクションを使用する永続クラスは、リレーションシップ属性を値ホルダー属性に置き換える必要があります。ValueHolderは、ValueHolder
など、ValueHolderInterface
インタフェースを実装するクラスのインスタンスです。このオブジェクトには、置き換えられるオブジェクトをデータベースから取得するために必要な情報が格納されます。アプリケーションがValueHolderにアクセスしないと、置き換えられたオブジェクトはデータベースから読み取られません。
ValueHolderが置き換えるオブジェクトを取得するには、ValueHolderInterface
のgetValue
およびsetValue
メソッドを使用します。これらのメソッドを使用する便利な方法としては、次の例で示すように、ValueHolderInterface
のgetValue
およびsetValue
メソッドを、get
およびset
メソッド内で非表示にする方法があります。
図7-9に、データベースから読み取られるEmployee
オブジェクトを示します。Address
オブジェクトは読み取られず、アクセスするまで作成されません。
図7-10に示すとおり、最初のアドレスへのアクセス時に、ValueHolder
はAddress
オブジェクトを読み取り、それを返します。
図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); } }
透過インダイレクションでは、次のいずれかの関連オブジェクトのコレクションを保持する永続クラスの任意のリレーションシップ属性を宣言します。
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項「ウィービングについて」を参照してください。
JavaクラスのProxy
を使用して、定義済インタフェースのプレースホルダとして動的プロキシ・オブジェクトを使用できます。特定のEclipseLinkマッピングを構成してプロキシ・インダイレクションを使用し、EclipseLinkクラスをドメイン・モデルに含めることなく、インダイレクションの利点を得ることができます。プロキシ・インダイレクションは1対1リレーションシップ・マッピングに対応し、インダイレクション・コンテナはコレクション・マッピングに対応します。
プロキシ・インダイレクションを使用するには、ドメイン・モデルが次の条件をすべて満たしている必要があります。
1対1リレーションシップのターゲット・クラスがパブリック・インタフェースを実装していること
ソース・クラスの1対1属性が、interface
タイプである必要があります。
メソッド・アクセスを使用する場合、getterメソッドおよびsetterメソッドはインタフェースを使用する必要があります。
プロキシ・インダイレクションを使用する前に、作業ユニットの使用方法で設定されている制限に注意してください(7.2.4.1項「プロキシ・インダイレクションの制限」を参照)。
プロキシ・インダイレクションを構成するため、修正メソッドでJDeveloperまたはJavaを使用できます。
Javaのプロキシ・オブジェクトは、送信されるメッセージの遮断にのみ使用できます。==
、instanceof
またはgetClass
などのプリミティブ操作がプロキシで使用されている場合は、メッセージは遮断されません。プロキシ・オブジェクトの使用に関しては、アプリケーションでこの制限に多少注意することが必要です。
プロキシ・インダイレクションの実装のターゲットは作業ユニットに登録できません。かわりに、先にソース・オブジェクトを作業ユニットに登録します。これにより、ソース・オブジェクト・クローンでgetterコールを使用し、ターゲット・オブジェクト・クローンを取得できます。
ウィービング用に構成したJPAエンティティまたはPOJOクラスの場合、EclipseLinkでは、1対1マッピングのValueHolderインダイレクションのウィービングが実行されます。アプリケーションにコレクション・マッピング(1対多または多対多)が含まれている場合にEclipseLinkで変更追跡に対するウィービングが実行されるようにするには、すべてのコレクション・マッピングに対し、透過インダイレクト・コンテナ・インダイレクションのみが使用されるように構成する必要があります(コレクション・マッピングは、即時ロードやValueHolderインダイレクションが使用されるようには構成できません)。
詳細は、3.3.1.4項「Javaバイト・コード・ウィービングの使用」を参照してください。
マッピングの注釈属性fetch
をlazy
に設定すると、EclipseLink JPA永続性プロバイダでインダイレクションが使用されます。
デフォルトでは、1対多リレーションシップおよび多対多リレーションシップはLAZYで、透過インダイレクションが使用されます。一方、1対1リレーションシップおよび多対1リレーションシップはLAZYではありません。
1対1リレーションシップおよび多対1リレーションシップをLAZYに設定してウィービングを有効にすると、EclipseLink JPA永続性プロバイダでは、ウィービングを介して、これらのリレーションシップに対するValueHolderインダイレクションが有効になります。
詳細は、次を参照してください。
インダイレクション(遅延ロード)を使用している場合、永続オブジェクトのグラフにトリガーされていないインダイレクション・オブジェクトが含まれる可能性があります。インダイレクション・オブジェクトは一時オブジェクトで、1つのJVMと別のJVMの間でシリアライズが存続することはないため、トリガーされていないインダイレクション・オブジェクトでは、デシリアライズ後にリレーションシップへのアクセスが行われるとエラーがトリガーされます。
アプリケーションでは、デシリアライズ後に必要なインダイレクト・リレーションシップがシリアライズ前にインスタンス化されていることを確認する必要があります。これを行うには、ValueHolder
またはウィービング済インダイレクションを使用して任意のリレーションシップのgetメソッドにアクセスし、透過インダイレクションを使用して任意のリレーションシップのsize
メソッドをコールします。アプリケーションで、シリアライズ時にリレーションシップを常にインスタンス化する場合、永続クラスのシリアライズwriteObject
メソッドを上書きして、最初に目的のリレーションシップをインスタンス化できます。多数のリレーションシップや階層の深いリレーションシップを持つオブジェクトでは、ラージ・オブジェクト・グラフをシリアライズしないように注意してください(クライアントで必要とされるリレーションシップのみがインスタンス化されるのが理想的です)。
JPAエンティティをシリアライズする場合、シリアライズの前にインスタンス化されていない遅延リレーションシップは、アクセスされるとエラーの原因となります。ウィービングをサーバーで使用し、エンティティをクライアントにシリアライズする場合、jarの静的ウィービングを通じて、またはEclipseLinkエージェントを使用したクライアントJVMの起動を通じて、同じウィービング・クラスがクライアントに存在している必要があります。
詳細は、3.3.1.4項「Javaバイト・コード・ウィービングの使用」を参照してください。
この項では、EclipseLinkに固有の非リレーショナル・マッピングの概念について説明します。
シンプル・タイプ変換は、ダイレクト・マッピングおよびダイレクト・コレクション・マッピングとともに使用し、XMLスキーマで定義したとおり、要素の<type>
属性に基づいて、XML要素の値を適切なJavaタイプに自動的に変換できます。
注意: シンプル・タイプ変換は、XMLプロジェクトにのみ適用されます。 |
コードでは、これは、次のようにXMLField
のsetIsTypedTextField
メソッドを使用してマッピングを作成する場合に設定されます。
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属性は、タイプの保持に必要な具体的な情報が不足している点に注意してください。シンプル・タイプ変換では、タイプを保持するためにタイプ情報を結果の文書に追加します。
デフォルトでは、EclipseLinkでは組込みの読取りおよび書込み変換ペアが使用されます(7.3.1.1項「デフォルトの読取り変換」および7.3.1.2項「デフォルトの書込み変換」を参照)。
独自のシンプル・タイプ変換の指定および構成によってこの動作をオーバーライドして、たとえば、XMLバイナリ・データをBase64
として書き込むことができます。
表7-2は、XML要素を読み取るための、組込みの変換ペアのリストを示しています。スキーマ<type>
属性が指定され、シンプル・タイプ変換が有効な場合、読み取られた値は対応するJavaタイプに変換されます。
EclipseLink MOXyでは、JSON (JavaScript Object Notation)を対象とするオブジェクトの変換機能がサポートされます。この機能は、RESTfulサービスを作成する場合に便利です(JAX-RSサービスはXMLとJSON両方のメッセージを受け取ることができます)。
EclipseLinkは、次のようなJSONの読取り時と書込み時のすべてのMOXyオブジェクト/XMLオプションに対応しています。
EclipseLinkの高度な拡張マッピング機能(JAXB仕様に対する追加)
外部バインディング・ファイルへのマッピングの格納
動的JAXBによる動的モデルの作成
マルチテナント・アプリケーションをサポートする拡張可能モデルの作成
EclipseLinkでは、JSON文書のマッピングに次のサポートが提供されます。
通常のJAXBでの使用に必要とされるもの以外は、JSONバインディングでコンパイル時の依存性は必要ありません。JSON文書としてMOXy外部バインディング・ファイルを書き込むこともできます。
XMLは単一のデータ型を保持しますが、JSONは文字列、数値、ブール値を区別します。EclipseLinkでは、これらのデータ型が自動的にサポートされます。
JSONでは属性は使用されず、@XmlAttribute
注釈を使用してマップされたものはすべて要素としてマーシャリングされます。デフォルトでは、EclipseLinkによって属性および要素のイベントが両方ともトリガーされるため、マップされた属性または要素で値を処理できます。
EclipseLinkでは、ルート要素のないJSON文書がサポートされます。デフォルトで、@XmlRootElement
注釈が存在しない場合、マーシャリングされたJSON文書にルート要素は含まれません。EclipseLinkでは、この動作をオーバーライドできます(JSON出力からルート要素を省略できます)。
JSONではネームスペースを使用しないため、すべてのネームスペースおよび接頭辞は、マーシャリングおよびアンマーシャリング時にデフォルトで無視されます。EclipseLinkでは、マーシャラおよびアンマーシャラに、ネームスペースと接頭辞のMap
(またはNamespacePrefixMapper
のインスタンス)を提供できます。ネームスペース接頭辞は、要素名の先頭に追加されて、マーシャリングされた文書に出現します。
デフォルトでは、JSONへのマーシャリング時に、EclipseLinkは空のコレクションを[ ]としてマーシャリングしますが、この動作をオーバーライドして、空のコレクションをまったくマーシャリングしないようにできます。
ルート・レベルのコレクションをマーシャリングおよびアンマーシャリングできます。
JSON文書に対するEclipseLinkサポートの詳細は、『Oracle Fusion Middleware Oracle TopLinkによるJAXBアプリケーションの開発』のJSON文書の使用に関する項を参照してください。
リレーショナル表にエンティティ・クラスをマップするには、永続フィールドごとにマッピングを構成する必要があります。次の項では、EclipeLinkのJPAマッピング・タイプについて説明します。
シンプルJavaタイプは、エンティティの即時状態の一部としてそのフィールドまたはプロパティにマップされます。シンプルJavaタイプのマッピングは、基本マッピングと呼ばれます。
デフォルトでは、EclipseLink永続性プロバイダによって、シンプル・タイプの基本マッピングが自動的に構成されます。
次の注釈を使用して、アプリケーションでこれらのマッピングを実装する方法を調整します。
@Basic
@Enumerated
@Temporal
@Lob
@Transient
@Column
遅延の基本(7.1.3項「遅延ロードの使用」を参照)
すべてのマッピング・タイプに、オプションの共通セットがあります。
読取り専用: 読取りおよびコピー時にマッピングで値の移入を行うように指定します。複数のマッピングで同じデータベース列を共有する場合には必須です。
コンバータ: ほとんどのマッピング・タイプでカスタム・データ・タイプおよびデータの変換を使用できます。
注釈: @Converter
、@TypeConverter
、@ObjectTypeConverter
、@StructConverter
、@Convert
外部メタデータ: <converter>
、<type-converter>
、<object-type-converter>
、<struct-converter>
、<convert>
これらの注釈の詳細は、『Oracle Fusion Middleware Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』を参照してください。
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)拡張機能リファレンス』を参照してください。
DescriptorCustomizer
クラスを使用して、EclipseLinkディスクリプタおよびマッピングAPIを通じて追加の拡張マッピングおよびマッピング・オプションにアクセスできます。
1対多マッピングは、1つのソース・オブジェクトとターゲット・オブジェクトのコレクションの間の関連を表すために使用されます。それらは、ターゲット・オブジェクトのCollection(または他のコレクション・タイプ)によるJavaでの実装が簡単だが、リレーショナル・データベースによる実装が難しいもののよい例です。
Javaコレクションでは、所有者がその一部を参照します。リレーショナル・データベースでは、その一部がその所有者を参照します。リレーショナル・データベースでは、この実装を使用して問合せをより効率的にします。
注意: 1対多リレーションシップに示されているphone属性のタイプは、Vectorです。コレクション属性の宣言にはCollectionインタフェース(またはCollectionインタフェースを実装する任意のクラス)を使用できます。 |
デフォルトで、JPAでは、1対多の多重度を持つ多値のアソシエーションに対してOneToManyマッピングを自動的に定義します。
@OneToMany
注釈を使用して次の操作を行います。
フェッチ・タイプをEAGER
に構成します。
関連するターゲット・エンティティを構成します(使用されるコレクションは汎用を使用して定義されないため)。
アソシエーションのターゲットにカスケードする必要のある操作を構成します(たとえば、所有側エンティティが削除されると、アソシエーションのターゲットも削除されます)。
単方向の1対多リレーションシップのために永続性プロバイダによって使用される結合表の詳細を構成します。mappedBy
またはJoinColumn
を使用する1対多では、関連オブジェクトの削除がデータベース上でカスケードされます。JoinTable
を使用する1対多では、結合表の削除がデータベース上でカスケードされます(ターゲット・オブジェクトは、制約方向のためにプライベートであってもカスケードされません)。
詳細は、JPA仕様の11.1.23項「JoinTable Annotation」を参照してください。
多対多マッピングは、ソース・オブジェクトのコレクションとターゲット・オブジェクトのコレクションの間のリレーションシップを表します。この場合、ソースとターゲットのレコード間の関連を管理するための中間表の作成が必要です。
図7-14は、Javaの多対多マッピングおよびリレーショナル・データベース表の多対多マッピングを示しています。
注意: 多対多リレーションシップに示されているプロジェクト属性では、コレクション属性を宣言するためにCollectionインタフェース(またはCollectionインタフェースを実装する任意のクラス)を使用できます。 |
デフォルトで、JPAでは、多対多の多重度を持つ多値のアソシエーションに対してManyToManyマッピングを自動的に定義します。
@ManyToMany
注釈を使用して次の操作を行います。
フェッチ・タイプをEAGER
に構成します。
NULL値がアプリケーションにとって不適切である場合、NULL値を禁止するようにマッピングを構成します(非プリミティブ・タイプの場合)。
関連するターゲット・エンティティを構成します(使用されるコレクションは汎用を使用して定義されないため)。
アソシエーションのターゲットにカスケードする必要のある操作を構成します(たとえば、所有側エンティティが削除されると、アソシエーションのターゲットも削除されます)。
@ManyToMany
注釈でサポートされる属性のリストは、Java Persistence仕様を参照してください。
オプティミスティック・ロックの使用をお薦めします。オプティミスティック・ロックを使用した場合、すべてのユーザーにデータへの読取りアクセス権限があります。ユーザーが変更を書き込もうとすると、アプリケーションにより、ユーザーがデータを読み取ってから、そのデータが変更されていないかが確認されます。
ステートレス環境では、期限切れの(失効した)データを処理しないよう、特に注意する必要があります。失効したデータを処理しないための一般的な方法は、オプティミスティック・ロックを実装し、オプティミスティック・ロックの値をオブジェクトに格納することです。この方法は、ステートレス・アプリケーションがオブジェクトをシリアライズする場合、またはオブジェクトの内容を代替形式でクライアントに送信する場合には、十分注意して行う必要があります。これらの場合、オプティミスティック・ロックの値を編集ページのHTTPコンテンツとしてクライアントに転送します。次に、任意の書込みトランザクションの戻り値を使用して、クライアントが処理を実行しているときに、データが変更されていないことを確認する必要があります。
オプティミスティック・バージョン・ロック・ポリシーまたはオプティミスティック・フィールド・ロック・ポリシーを使用できます。バージョン・ロック・ポリシーの使用をお薦めします。
@Version注釈を使用して、オプティミスティック・ロックの値として機能するエンティティ・クラスのバージョン・フィールドまたはプロパティを指定することで、JPA管理のオプティミスティック・ロックを有効化できます(推奨)。
バージョン・フィールドまたはプロパティを選択する場合、次の条件を満たす必要があります。
1つのエンティティに対してただ1つのバージョン・フィールドまたはプロパティがあること
プライマリ表に永続化されたプロパティまたはフィールドを選択すること
アプリケーションでバージョン・プロパティまたはフィールドを変更しないこと
詳細は、JPA仕様の11.1.45項「Table Annotation」を参照してください。
http://jcp.org/en/jsr/detail?id=317
注意: フィールドまたはプロパティ・タイプは、数値型( |
@Version
注釈には属性はありません。@Version
注釈では、EclipseLinkコンバータの使用がサポートされます。7.5.2項「デフォルトの変換およびコンバータ」を参照してください。
詳細は、JPA仕様の11.1.9項「Column Annotation」を参照してください。