この章では、マッピングについて紹介および説明します。EclipseLinkでは、オブジェクト表現とデータ・ソース固有の表現との間でデータのトランスフォーメーションを実行できます。このトランスフォーメーションをマッピングと呼びますが、マッピングは、EclipseLinkプロジェクトの中核をなしています。
マッピングはそれぞれ、ドメイン・オブジェクトの単一データ・メンバーに対応しています。マッピングによって、オブジェクト・データ・メンバーをそのデータ・ソース表現と関連付け、オブジェクトとデータ・ソースの間の双方向変換を実行する手段を定義します。
この章の内容は次のとおりです。
この項では、EclipseLinkに固有のリレーショナル・マッピングと非リレーショナル・マッピングの概念について説明します。
マッピングを定義するには、次のコンポーネントを利用します。
オブジェクトのデータを格納するデータ・ソース(リレーショナル・データベース表またはスキーマ定義のXML要素など)に固有のデータ表現
特定オブジェクト・クラスのディスクリプタ
マップするオブジェクト・クラス
注意: マッピングは、プロジェクトの永続性の有無にかかわりなく同じです。 |
標準的なEclipseLinkマッピングの例については、6.1.2項「マッピングの例」を参照してください。
プロジェクトで定義するデータ・ソースのタイプによって、使用できるマッピングのタイプおよびその構成方法が決まります。永続プロジェクトでは、マッピングを使用してデータ・ソースを永続させます。永続ではないプロジェクトでは、オブジェクト形式とその他の一部のデータ表現(XMLなど)の間で単に変換を行うためにマッピングを使用します。
ディスクリプタは、特定のドメイン・オブジェクトを表し、オブジェクトのクラスを記述します。ディスクリプタは、マッピングも所有します(メモリー内で永続化または変換するクラス・データ・メンバーごとに1つのマッピング)。ディスクリプタの詳細は、第5章「ディスクリプタの理解」を参照してください。
EclipseLinkでは、より複雑なマッピングをサポートしますが、ほとんどのEclipseLinkのクラスは、クラスで使用可能な情報のタイプを定義する1つのデータベース表またはXML要素にマップされます。特定のクラスからインスタンス化された各オブジェクトは、一意にオブジェクトを識別する識別子(主キー)を付加して、オブジェクトの属性を構成する1つの行にマップされます。
図6-1は、最も単純なデータベース・マッピングの例を示します。
データベースのTable_Xは、Class_Xを表します。
Object_X1およびObject_X2は、Class_Xのインスタンスです。
Table_Xの各行は、Object_X1およびObject_X2に加えて、Class_Xのその他のインスタンスも表します。
EclipseLinkには、図6-1に示した単純なマッピングから複雑なマッピングまで、これらのマッピングを作成するためのツールが用意されています。
リレーショナル・マッピングのその他の例は、図6-2「シリアライズ・オブジェクト・コンバータ(リレーショナル)」を参照してください。
既存のEclipseLinkマッピングがニーズを満たしていない場合、マッピングの拡張機能を使用してカスタムのマッピングを作成できます。これらの拡張機能は、次のとおりです。
注意: シンプル・タイプ変換以外では、データ・ソースがリレーショナルかリレーショナルでないかにかかわらず、マッピング・コンバータおよびトランスフォーマを使用できます。シンプル・タイプ変換は、XMLプロジェクトにのみ適用されます。 |
シリアライズ・オブジェクト・コンバータは、Javaオブジェクト・シリアライズを介して複雑なオブジェクトをバイナリ・フィールドにマップできるダイレクト・マッピングおよびダイレクト・コレクション・マッピングで使用できます。シリアライズされたオブジェクトは、通常、データベースのRAW
またはバイナリ・ラージ・オブジェクト(BLOB
)フィールド、またはXML文書のHEX
またはBASE64
要素に格納されます。
図6-2は、シリアライズ・オブジェクト・コンバータを使用したフィールドへ直接マッピングの例を示しています。属性jobDescription
には、データベースのJOB_DESC
フィールドに格納される、書式設定されたテキスト文書が含まれています。
図6-3に、シリアライズ・オブジェクト・コンバータを使用する非リレーショナル・マッピングの例を示します。属性jobDescription
には、EclipseLinkによってXMLスキーマのJOB DESCRIPTION
要素に格納される、書式設定されたテキスト文書が含まれています。
シリアライズ・オブジェクト・コンバータは、Javaシリアライザを利用します。ドメイン・オブジェクトをシリアライズ・オブジェクト・コンバータでマップする前に、ドメイン・オブジェクトにjava.io.Serializable
インタフェースが実装され(または実装が継承され)、シリアライズされていないすべてのフィールドにtransientがマークされていることを確認してください。
タイプ変換コンバータは、複雑なオブジェクトをバイナリ・フィールドにマップできるダイレクト・マッピングおよびダイレクト・コレクション・マッピングで使用できます。たとえば、データ・ソースのNumber
をJavaのString
にマップすることや、Javaのjava.util.Date
をデータ・ソースのjava.sql.Date
にマップすることができます。
図6-4に、タイプ変換マッピング(リレーショナル)の例を示します。java.util.Date
クラスは、デフォルトではTimestamp
としてデータベースに格納されるため、そのクラスは、まず、java.sql.Date
のような明示的なデータベース・タイプに変換する必要があります(これはDB2に対してのみ必須であり、その他の大部分のデータベースには、任意の日付または時間を格納できる単一日付のデータ・タイプがあります)。
図6-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
タイプに変換する場合は、トランスフォーメーション・マッピングを検討してください(6.1.4項「トランスフォーメーション・マッピング」を参照)。
@TypeConverter
注釈を使用して、マップ済属性の読取りおよび書込み中にデータ値を変更することもできます。各TypeConverter
は、一意の名前を付ける必要があり、クラス、フィールドおよびプロパティ・レベルで定義でき、Entity
、MappedSuperclass
およびEmbeddable
クラス内で指定できます。TypeConverter
は、常に@Convert
注釈を使用して指定されます。
@TypeConverter
をBasic
、BasicMap
またはBasicCollection
マッピングに配置できます。これらの注釈の詳細は、『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』を参照してください。
オブジェクト・タイプ・コンバータは、一定数の値をJavaオブジェクトに対応させることができるダイレクト・マッピングおよびダイレクト・コレクション・マッピングで使用できます。このコンバータは、スキーマにある値がJavaにある値と異なる場合に使用します。
図6-6は、Employee
属性のgender
とXML要素のgender
との間のオブジェクト・タイプの変換を示しています。Javaのオブジェクト属性の値がFemale
の場合、EclipseLinkではその値がF
としてXML要素に格納されます。
@ObjectTypeConverter
注釈を使用した、オブジェクト・タイプの変換の実行もできます。この注釈は、マップ済属性の読取りおよび書込み中にデータベース・データ値の固定数をJavaオブジェクト値に変換するorg.eclipse.persistence.mappings.converters.ObjectTypeConverter
を指定します。この注釈には、@ConversionValue
注釈を使用して、変換値の配列に対する値を提供する必要があります。詳細は、『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』の@ObjectTypeConverter
および@ConversionValue
の説明を参照してください。
ある種の特殊な状況においては、データ・ソースの処理に関して、既存のマッピング・タイプおよびそのデフォルトのJavaでは、不十分な場合が考えられます。このような特殊なケースでは、Javaでの値の表現とデータ・ソースでの値の表現の間で、特殊な変換を実行するためのトランスフォーメーション・マッピングの使用を検討できます。
ヒント: トランスフォーメーション・マッピングは複雑なため、多くの場合、コンバータまたはフィールドへ直接マッピングのgetterおよびsetterメソッドを使用する方が簡単に変換を実行できます。 |
図6-7は、トランスフォーメーション・マッピングを示しています。B_DATE
およびB_TIME
フィールドからの値は、birthDate
属性に格納されるjava.util.Date
の作成に使用されます。
トランスフォーメーション・マッピングは、次の2つのコンポーネントで構成されています。
属性トランスフォーマ: 読取り時にオブジェクト属性トランスフォーメーションを実行します。
フィールド・トランスフォーマ: 書込み時にオブジェクト属性からフィールドへのトランスフォーメーションを実行します。
トランスフォーマは、別個のクラスまたはドメイン・オブジェクトでのメソッドのいずれかとして実装できます。
多くの場合、トランスフォーメーション・マッピングは、複数のフィールドの値を使用して1つのオブジェクトを作成する場合に適しています。このタイプのマッピングでは、データベースからオブジェクトを読み取る際に起動される、属性トランスフォーメーションが必要です。これには、Record
のインスタンスであるパラメータを1つ以上持たせる必要があります。属性トランスフォーメーションでは、特定の列の値の取得にRecord
メソッドget
を使用できます。属性トランスフォーメーションは、オプションで2番目のパラメータ(Session
のインスタンス)を指定できます。Session
は、トランスフォーメーションで必要な追加の値を取得するために、データベースで問合せを実行します。トランスフォーメーションにより、属性に格納される値が返されます。
トランスフォーメーション・マッピングでは、オブジェクトが保存される際にデータベースに書き込まれる、各フィールドに対するフィールド・トランスフォーメーションも必要です。トランスフォーメーションは、そのフィールドに格納される値を返します。
属性およびフィールド・トランスフォーメーションの実装時には、アプリケーション・データをデータ・ソースに、またはその逆に適合させるための変換に必要な、どのような処置も講じることができます。
@Transformation
属性を使用して、データベース列値と属性値のトランスフォーメーション・マッピングを実行できます。@WriteTransformer
および@ReadTransformer
注釈とともにこの注釈を使用します。@WriteTransformer
注釈は、単一の属性値を単一のデータベース列値に変換するために使用します。この注釈については、FieldTransformer
インタフェースの実装を提供することもできます。@ReadTransformer
注釈については、org.eclipse.persistence.mappings.transformers.AttributeTransformer
インタフェースの実装を提供する必要があります。これらの注釈の詳細は、『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』の @Transformation
、@ReadTransformer
および@WriteTransformer
に関する説明を参照してください。
この項では、EclipseLinkに固有のリレーショナル・マッピングの概念について説明します。
デフォルトでは、EclipseLinkは永続オブジェクトを取得する際に、そのオブジェクトが参照する依存オブジェクトをすべて取得します。リレーションシップ・マッピングによってマップされた属性に対してインダイレクション(遅延読取り、遅延ロードおよびジャストインタイム読取りとも呼びます)を構成すると、参照オブジェクトのプレースホルダとしてインダイレクション・オブジェクトが使用されます(EclipseLinkは、その特定の属性がアクセスされるまで、依存オブジェクトの読取りを遅延します)。その結果、アプリケーションにとって重要なのは取得されたオブジェクトの内容のみであり、関連オブジェクトの内容は重要でないという場合は特に、パフォーマンスが大幅に向上します。
すべての関連マッピングに対してインダイレクションを使用することをお薦めします。これにより、データ・ソースへのアクセスを最適化できるだけでなく、永続性ユニット処理、キャッシュ・アクセスおよび同時実行性のEclipseLinkによる最適化が可能になります。
注意:
|
図6-8に、インダイレクションの例を示します。インダイレクションを使用しない場合、Order
オブジェクトを読み取ると、LineItem
オブジェクトの依存コレクションも読み取られます。インダイレクションを使用する場合、Order
オブジェクトを読み取っても、LineItem
オブジェクトの依存コレクションは読み取られません(lineItems
属性は、インダイレクション・オブジェクトを参照します)。customerId
などの他の属性にはアクセスできますが、EclipseLinkが依存LineItem
オブジェクトを読み取るのは、lineItems
属性にアクセスがあった場合のみです。
EclipseLinkでは、次のインダイレクション・タイプをサポートします。
アプリケーションのシリアライズ対象となるオブジェクトにインダイレクションを使用する場合、デシリアライズ時にトリガーされないインダイレクション・オブジェクトの影響を検討する必要があります。6.2.2項「インダイレクション、シリアライズおよびデタッチ」を参照してください。
インダイレクション(遅延ロード)を使用している場合、永続オブジェクトのグラフにトリガーされていないインダイレクション・オブジェクトが含まれる可能性があります。インダイレクション・オブジェクトは一時オブジェクトで、1つのJVMと別のJVMの間でシリアライズが存続することはないため、トリガーされていないインダイレクション・オブジェクトでは、デシリアライズ後にリレーションシップへのアクセスが行われるとエラーがトリガーされます。
アプリケーションでは、デシリアライズ後に必要なインダイレクト・リレーションシップがシリアライズ前にインスタンス化されていることを確認する必要があります。これを行うには、ValueHolder
またはウィービング済インダイレクションを使用して任意のリレーションシップのgetメソッドにアクセスし、透過インダイレクションを使用して任意のリレーションシップのsize
メソッドをコールします。アプリケーションで、シリアライズ時にリレーションシップを常にインスタンス化する場合、永続クラスのシリアライズwriteObject
メソッドを上書きして、最初に目的のリレーションシップをインスタンス化できます。多数のリレーションシップや階層の深いリレーションシップを持つオブジェクトでは、ラージ・オブジェクト・グラフをシリアライズしないように注意してください(クライアントで必要とされるリレーションシップのみがインスタンス化されるのが理想的です)。
JPAエンティティをシリアライズする場合、シリアライズの前にインスタンス化されていないLAZYリレーションシップは、アクセスされるとエラーの原因となります。ウィービングをサーバーで使用し、エンティティをクライアントにシリアライズする場合、jarの静的ウィービングを通じて、またはEclipseLinkエージェントを使用したクライアントJVMの起動を通じて、同じウィービング・クラスがクライアントに存在している必要があります。
詳細は、3.2.1.4項「Javaバイト・コード・ウィービングの使用」を参照してください。
インダイレクションを使用する永続クラスは、リレーションシップ属性を値ホルダー属性に置き換える必要があります。ValueHolderは、ValueHolder
など、ValueHolderInterface
インタフェースを実装するクラスのインスタンスです。このオブジェクトには、置き換えられるオブジェクトをデータベースから取得するために必要な情報が格納されます。アプリケーションがValueHolderにアクセスしないと、置き換えられたオブジェクトはデータベースから読み取られません。
ValueHolderが置き換えるオブジェクトを取得するには、ValueHolderInterface
のgetValue
およびsetValue
メソッドを使用します。これらのメソッドを使用する便利な方法としては、次の例で示すように、ValueHolderInterface
のgetValue
およびsetValue
メソッドを、get
およびset
メソッド内で非表示にする方法があります。
図6-9に、データベースから読み取られるEmployee
オブジェクトを示します。Address
オブジェクトは読み取られず、アクセスするまで作成されません。
図6-10に示すとおり、最初のアドレスへのアクセス時に、ValueHolder
はAddress
オブジェクトを読み取り、それを返します。
図6-11で示すように、アドレスに対する後続のリクエストではデータベースにアクセスしません。
メソッド・アクセスを使用している場合、マッピングで指定されたgetおよびsetメソッドは、ValueHolderが参照しているオブジェクトではなく、ValueHolderInterface
のインスタンスにアクセスする必要があります。アプリケーションがこれらのgetterおよびsetterを使用することはありませんが、ValueHolderの使用を隠すgetterおよびsetterを使用します。
透過インダイレクションでは、次のいずれかのJavaオブジェクトとして関連オブジェクトのコレクションを保持する永続クラスの任意のリレーションシップ属性を宣言します。
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.2.1.4項「Javaバイト・コード・ウィービングの使用」および3.5項「ウィービングについて」を参照してください。
JavaクラスのProxy
を使用して、定義済インタフェースのプレースホルダとして動的プロキシ・オブジェクトを使用できます。特定のEclipseLinkマッピングを構成してプロキシ・インダイレクションを使用し、EclipseLinkクラスをドメイン・モデルに含めることなく、インダイレクションの利点を得ることができます。プロキシ・インダイレクションは1対1リレーションシップ・マッピングに対応し、インダイレクション・コンテナはコレクション・マッピングに対応します。
プロキシ・インダイレクションを使用するには、ドメイン・モデルが次の条件をすべて満たしている必要があります。
1対1リレーションシップのターゲット・クラスがパブリック・インタフェースを実装していること
ソース・クラスの1対1属性が、interface
タイプである必要があります。
メソッド・アクセスを使用する場合、getterメソッドおよびsetterメソッドはインタフェースを使用する必要があります。
プロキシ・インダイレクションを使用する前に、永続性ユニットの使用方法で設定されている制限に注意してください(6.2.5.1項「プロキシ・インダイレクションの制限」を参照)。
プロキシ・インダイレクションを構成するため、修正メソッドでJDeveloperまたはJavaを使用できます。
Javaのプロキシ・オブジェクトは、送信されるメッセージの遮断にのみ使用できます。==
、instanceof
またはgetClass
などのプリミティブ操作がプロキシで使用されている場合は、メッセージは遮断されません。プロキシ・オブジェクトの使用に関しては、アプリケーションでこの制限に多少注意することが必要です。
プロキシ・インダイレクションの実装のターゲットは永続性ユニットに登録できません。かわりに、先にソース・オブジェクトを永続性ユニットに登録します。これにより、ソース・オブジェクト・クローンでgetterコールを使用し、ターゲット・オブジェクト・クローンを取得できます。
ウィービング用に構成したJPAエンティティまたはPOJOクラスの場合、EclipseLinkでは、1対1マッピングのValueHolderインダイレクションのウィービングが実行されます。アプリケーションにコレクション・マッピング(1対多または多対多)が含まれている場合にEclipseLinkで変更追跡に対するウィービングが実行されるようにするには、すべてのコレクション・マッピングに対し、透過インダイレクト・コンテナ・インダイレクションのみが使用されるように構成する必要があります(コレクション・マッピングは、即時ロードやValueHolderインダイレクションが使用されるようには構成できません)。
詳細は、3.2.1.4項「Javaバイト・コード・ウィービングの使用」を参照してください。
リレーショナル表にエンティティ・クラスをマップするには、永続フィールドごとにマッピングを構成する必要があります。次の項では、EclipeLinkのJPAマッピング・タイプについて説明します。
シンプルJavaタイプは、エンティティの即時状態の一部としてそのフィールドまたはプロパティにマップされます。シンプルJavaタイプのマッピングは、基本マッピングと呼ばれます。
デフォルトでは、EclipseLink永続性プロバイダによって、シンプル・タイプの基本マッピングが自動的に構成されます。
次の注釈を使用して、アプリケーションでこれらのマッピングを実装する方法を調整します。
@Basic
@Enumerated
@Temporal
@Lob
@Transient
@Column
遅延の基本(6.2.7.3.5項「コレクションを使用したインダイレクションの使用」を参照してください)
すべてのマッピング・タイプに、オプションの共通セットがあります。
読取り専用: 読取りおよびコピー時にマッピングで値の移入を行うように指定します。複数のマッピングで同じデータベース列を共有する場合には必須です。
コンバータ: ほとんどのマッピング・タイプでカスタム・データ・タイプおよびデータの変換を使用できます。
注釈: @Converter
、@TypeConverter
、@ObjectTypeConverter
、@StructConverter
、@Convert
外部メタデータ: <converter>
、<type-converter>
、<object-type-converter>
、<struct-converter>
、<convert>
これらの注釈の詳細は、『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』を参照してください。
『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』のコンバータ注釈に関する項には、EclipseLinkが定義するコンバータ注釈の拡張のリストおよび説明へのリンクが記載されています。
次の説明については、『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』の個々のコンバータ注釈を参照してください。
EclipseLink永続性プロバイダがコンバータ注釈を検索する順序
コンバータを指定するクラスのタイプ(クラス、フィールドおよびプロパティ・レベルでコンバータを定義できます)
コンバータを使用できるマッピング
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」を参照してください。
多対多マッピングは、ソース・オブジェクトのコレクションとターゲット・オブジェクトのコレクションの間のリレーションシップを表します。この場合、ソースとターゲットのレコード間の関連を管理するための中間表の作成が必要です。
図6-13は、Javaの多対多マッピングおよびリレーショナル・データベース表の多対多マッピングを示しています。
注意: 多対多リレーションシップに示されているプロジェクト属性では、コレクション属性を宣言するために |
デフォルトで、JPAでは、多対多の多重度を持つ多値のアソシエーションに対して多対多マッピングを自動的に定義します。
@ManyToMany
注釈を使用して次の操作を行います。
FetchType
をEAGER
に構成します。
NULL値がアプリケーションにとって不適切である場合、NULL値を禁止するようにマッピングを構成します(非プリミティブ・タイプの場合)。
関連するターゲット・エンティティを構成します(使用されるコレクションは汎用を使用して定義されないため)。
アソシエーションのターゲットにカスケードする必要のある操作を構成します(たとえば、所有側エンティティが削除されると、アソシエーションのターゲットも削除されます)。
@ManyToMany
注釈でサポートされる属性のリストは、Java Persistence仕様を参照してください。
JPAでは、遅延ロードを、データが最初にアクセスされたときに可能であれば遅延してフェッチするという永続性プロバイダに対するヒントとして規定しています。Java EE環境でアプリケーションを開発する場合、fetchをjavax.persistence.FetchType.LAZY
に設定し、必要なすべての機能を永続性プロバイダで提供します。
Java SE環境で1対1または多対1のマッピングを使用する場合、fetch
属性をFetchType.LAZY
に設定することで、動的ウィービングまたは静的ウィービングを使用して遅延ロードを実行します。また、Java SE環境では、1対多リレーションシップおよび多対多リレーションシップはデフォルトではLAZYで、透過インダイレクションが使用されます。一方、1対1リレーションシップおよび多対1リレーションシップはLAZYではありません。
Java SE環境や、JVMコマンド行で-javaagent
の使用が許可されない環境で1対1または多対1のマッピングを使用する場合、fetch
属性をFetchType.LAZY
に設定することで、静的ウィービングを使用して遅延ロードを実行します。
1対1リレーションシップおよび多対1リレーションシップをLAZYに設定してウィービングを有効にすると、EclipseLink JPA永続性プロバイダでは、ウィービングを介して、これらのリレーションシップに対するValueHolderインダイレクションが有効になります。
コレクション注釈@OneToOne
、@OneToMany
、@ManyToMany
および@ManyToOne
には、lazy
またはeager
に設定できるfetch
マッピング属性が用意されています。属性をlazy
に設定すると、EclipseLink JPA永続性プロバイダでインダイレクションが使用されます。
表6-1は、マッピング・タイプ別の遅延ロードのサポートを示しています。
表6-1 マッピング・タイプ別の遅延ロードのサポート
マッピング | Java EE | Java SE |
---|---|---|
多対多 |
|
|
1対多 |
|
|
1対1 |
|
|
多対1 |
|
|
基本 |
|
|
オプティミスティック・ロックの使用をお薦めします。オプティミスティック・ロックを使用した場合、すべてのユーザーにデータへの読取りアクセス権限があります。ユーザーが変更を書き込もうとすると、アプリケーションにより、ユーザーがデータを読み取ってから、そのデータが変更されていないかが確認されます。
ステートレス環境では、期限切れの(失効した)データを処理しないよう、特に注意する必要があります。失効したデータを処理しないための一般的な戦略は、オプティミスティック・ロックを実装し、オプティミスティック・ロックの値をオブジェクトに格納することです。この方法は、ステートレス・アプリケーションがオブジェクトをシリアライズする場合、またはオブジェクトの内容を代替形式でクライアントに送信する場合には、十分注意して行う必要があります。これらの場合、オプティミスティック・ロックの値を編集ページのHTTPコンテンツとしてクライアントに転送します。次に、任意の書込みトランザクションの戻り値を使用して、クライアントが処理を実行しているときに、データが変更されていないことを確認する必要があります。
オプティミスティック・バージョン・ロック・ポリシーまたはオプティミスティック・フィールド・ロック・ポリシーを使用できます。バージョン・ロック・ポリシーの使用をお薦めします。
@Version
注釈を使用して、オプティミスティック・ロックの値として機能するエンティティ・クラスのバージョン・フィールドまたはプロパティを指定することで、JPA管理のオプティミスティック・ロックを有効化できます(推奨)。
バージョン・フィールドまたはプロパティを選択する場合、次の条件を満たす必要があります。
1つのエンティティに対してただ1つのバージョン・フィールドまたはプロパティがあること
プライマリ表に永続化されたプロパティまたはフィールドを選択すること
アプリケーションでバージョン・プロパティまたはフィールドを変更しないこと
詳細は、JPA仕様の11.1.45項「Table Annotation」を参照してください。
http://jcp.org/en/jsr/detail?id=338
注意: フィールドまたはプロパティ・タイプは、数値型( |
@Version
注釈には属性はありません。@Version
注釈では、EclipseLinkコンバータを使用することができます。6.2.7.2項「デフォルトの変換およびコンバータ」を参照してください。
詳細は、JPA仕様の11.1.9項「Column Annotation」を参照してください。
XMLマッピングは、オブジェクトのデータ・メンバーを、構造がXMLスキーマ・ドキュメント(XSD)により定義されているXML文書のXML要素に変換します。様々なXMLマッピング・タイプを使用して、XMLの単純および複合型の組合せにJavaオブジェクトの属性をマップできます。
クラスは複合型にマップされ、オブジェクトの関係はXML要素にマップされ、単純属性はテキスト・ノードとXML属性にマップされます。MOXyを使用する場合の真価は、オブジェクト属性をXML文書にマッピングする際に、XPath文を使用してXMLデータの場所を指定できることにあります。
EclipseLinkでは、クラスのディスクリプタに各クラスのXMLマッピングを格納します。EclipseLinkでは、ディスクリプタを使用してXML文書からマップされたオブジェクトをインスタンス化し、新規または変更済のオブジェクトをXML文書として格納します。
EclipseLinkには、JAXB仕様には定義されていないXMLマッピングが用意されています。MOXyの拡張機能には、EclipseLinkの注釈を介して使用できるものと、基礎となるメタデータに対するプログラムの変更が必要なものがあります。
MOXyに対するマッピングの概念については、『Oracle TopLinkによるJAXBアプリケーションの開発』に記載されています。次の章を参照してください。
EclipseLink MOXyランタイムに関する章の内容は次のとおりです。
JAXB注釈に代わる、EclipseLink XMLバインディング・ドキュメント。XMLバインディングは、マッピング情報を実際のJavaクラスから分離できるだけでなく、高度なメタデータにも使用できます。
JAXBContext
の作成時に使用できる、何種類かのブートストラップ・オプション。
EclipseLinkメタデータの提供を担当する、MetadataSource
インタフェース。このインタフェースの実装の指定により、マッピング情報をアプリケーションの外部に保存して、アプリケーションのJAXBContext
が作成またはリフレッシュされるときにマッピング情報を取得できるようになります。
スキーマの生成および検証。
マーシャリング・プロセス中およびアンマーシャリング・プロセス中に、イベント・コールバックを取得する何種類かのメカニズム。マップされたオブジェクトにコールバック・メソッドを直接指定するか、または別のListener
クラスを定義し、JAXBランタイムに登録できます。
XPathによるオブジェクトの問合せ。これは、従来のJavaアクセス・メソッドに代わる、オブジェクトの値の取得および設定方法です。EclipseLink MOXyでは、XPath文を使用して値にアクセスすることができます。EclipseLinkのJAXBContext
には、XPathで値を取得および設定できるようにするための特殊なAPIがあります。
アイテムの一部のみがマップされている場合でもXML文書全体を保持できる、JAXB Binder
インタフェースの使用。
単純な値のマッピングに関する章では、MOXyでマッピングを設定する初期タスクについて説明しています。
XML文書の最上位レベルのルートが何になるかをEclipseLinkに通知する、デフォルトのルート要素。
Javaクラスの名前空間の情報、およびすべての要素が名前空間に対して修飾されている必要があること。パッケージ、タイプまたはフィールド/プロパティ・レベルの要素を名前空間に対して修飾できます。
xsi:type
属性、代替グループまたはMOXY固有の@XmlDiscriminatorNode
および@XmlDiscriminatorValue
注釈を使用して、XMLで継承階層を指定する方法
単純な値のマッピングに関する章および特殊なスキーマ・タイプのマッピングに関する章は、Java値をXMLにマップする様々な方法を説明しています。
Java値はXML属性、テキスト・ノード、スキーマ・タイプまたはシンプル・タイプ・トランスレータにマップできます。
単純なJava値のコレクションは、テキスト・ノード、グループ化要素内のテキスト・ノード、リスト要素またはXmlAttributes
またはXmlValues
のコレクションにマップできます。
OXMメタデータを使用して1つのプロパティに複数のJavaマッピングを作成できます。ただし、読取り可能なマッピングはせいぜい1つです(それ以外は「書込み専用」です)。
Javaenums
は、@XmlEnum
注釈と@XmlEnumValue
注釈を使用してXMLにマップできます。
日付と時間: また、EclipseLink MOXyは、JAXB仕様で扱われていない次の型をサポートしています。java.sql.Date
、java.sql.Time
およびjava.sql.Timestamp
。
unionファイル: EclipseLinkでXMLスキーマ・ユニオンなどのXML文書をアンマーシャリングする場合、正常な変換が行われるまで、union型のそれぞれが試行されます。現時点では、EclipseLinkは、注釈またはOXMメタデータを使用したunionのマッピングをサポートしていません。ただし、EclipseLinkのXMLカスタマイザを使用してマッピングを作成することはできます。
バイナリ形式: EclipseLinkでは、base64Binary
(デフォルト)とhexBinary
という、2つの表現形式でのバイナリ・データのマーシャリングおよびアンマーシャリングをサポートしています。EclipseLink OXMで@XmlSchemaType
注釈または<xml-schema-type>
要素を使用して、目的のバイナリ形式を指定できます。
JPAからXMLへのマッピングに注釈を使用することは、常に最も効果的とはかぎりません。たとえば、次の場合にはJAXBを使用しません。
サード・パーティのクラスにメタデータを指定する必要があるが、ソースにアクセスできない場合。
複数のXMLスキーマにオブジェクト・モデルをマップする必要がある場合。JAXBのルールでは、注釈を使用して複数のマッピングを適用することはできません。
オブジェクト・モデルにすでに多くの注釈(たとえば、JPA、Spring、JSR-303などのサービスから)が含まれていて、他の場所でメタデータを指定する必要がある場合。
これらの状況および類似の状況では、eclipselink_oxm.xml
ファイルを公開して、XMLデータ表現を使用できます。
XMLメタデータは、次の2つのモードで動作します。
注釈で指定されたメタデータに追加します。これは、次の場合に便利です。
XML表現のバージョンのひとつが注釈に定義されており、XMLメタデータを使用して将来のバージョンのメタデータを微調整する場合。
標準のJAXB注釈を使用し、かつMOXy拡張機能用のXMLメタデータを使用する場合。このようにすると、コンパイル時の依存関係がオブジェクト・モデルに新たに生じることはありません。
注釈メタデータを完全に置換します。これは、様々なXML表現にマップする必要がある場合に便利です。
単純なJava値および単純な値のコレクションを、XMLテキスト・ノードに直接マップする方法がいくつかあります。属性、テキスト・ノードまたはスキーマ・タイプにマップできます。シンプル・タイプ・トランスレータを使用して、XMLスキーマで定義されていないタイプのノードにマップすることもできます。これらの方法は『Oracle TopLinkによるJAXBアプリケーションの開発』の単純な値のマッピングに関する項に記載されています。
オブジェクト・リレーショナル・マッピングでは、EclipseLinkはFetchGroups
およびAttributeGroups
を定義して、特定のオブジェクトのどの属性を書き出し、どの属性を読み込むかを制御します。
現在のMOXy/JAXBリリースでは、マーシャリングおよびアンマーシャリングするオブジェクト属性のサブセットを構成できるようになりました。これを行うには、注釈のセットを使用して、ディスクリプタに属性グループを設定します。注釈は、XmlNamedObjectGraphs
、XmlNamedObjectGraph
、XmlNamedAttributeNode
およびXmlNamedSubGraph
です。Xml
接頭辞により同等のJPA注釈と区別されることに注意してください。
@XmlNamedObjectGraph
拡張機能は、マーシャリングまたはアンマーシャリングするモデルのサブセットの指定に使用します。1つ以上の@XmlNamedAttributeNode
注釈を指定することにより指定します。プロパティに適用されるオブジェクト・グラフが必要な場合、サブグラフを指定できます。サブグラフはターゲット・クラスの@XmlNamedSubgraph
または@XmlNamedObjectGraph
注釈のいずれかで指定できます。
インタフェースのセットも定義されているため、ObjectGraphs
を実行時に動的に作成できます。これらのObjectGraphs
は、事前定義済のObjectGraph
の名前のかわりにマーシャラまたはアンマーシャラに設定できます。インタフェースはObjectGraph
、Subgraph
およびAttributeNode
です。ObjectGraph
の新しいインスタンスを作成するため、メソッドがJAXBContext
クラスに含まれています。
MOXyの@XmlInverseReference
注釈により、アンマーシャル操作の間、バック・ポインタをマップできます(JPAエンティティをマッピングする場合に便利です)。ただし、マーシャル操作の間は@XmlTransient
のように動作します。これは、以前のリリースでは、マッピングは一方向のみにしか使用できなかったことを意味します。現在のリリースでは、@XmlInverseReference
注釈を@XmlElement
注釈と組み合せて、マーシャリング操作の間、プロパティを書込み可能にできるようになりました。これにより、マッピングを双方向に使用できるようになりました。
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 TopLinkによるJAXBアプリケーションの開発』のJSON文書の使用に関する項を参照してください。
デフォルトでは、JAXB実装はコレクション・データに関するグループ化要素を出力しません。しかし、@XmlElementWrapper
注釈をJSONキーとして使用することにより出力できます。このグループ化要素は複数形の名前を持つことも多く、@XmlElement
注釈で定義された繰返し要素よりは、JSON配列のキーにより良く適合します。
JSONPつまり「パディング付きJSON」は、Webブラウザで動作するJavaScriptが使用する通信技術です。一般的なWebブラウザでは同一生成元ポリシーにより禁止されている、異なるドメインのサーバーからデータを要求する方法を提供します。
JSONPと呼ばれる使用パターンは、<script>
要素のオープン・ポリシーを使用して、動的に生成されたJSON形式のデータで動作するJavaScriptコードを他の生成元から取得します。JSONPに対するリクエストはJSONを取得するかわりに、任意のJavaScriptコードを取得します。JavaScriptインタプリタが評価を行い、JSONパーサーによる解析は行われません。
MOXyには、MOXyJsonProvider
と呼ばれるMessageBodyReader
およびMessageBodyWriter
クラスの実装が用意されています。MOXyJsonProvider
クラスは、EclipseLink JAXB (MOXy)をJSONプロバイダとして有効化するために使用できます。このクラスを直接使用または拡張して、JAX-RS統合を容易にすることができます。次の拡張機能がMOXyJsonProvider
クラスに追加されています。
readFrom
およびwriteTo
メソッドのgenericType
パラメータで、NULL値を使用できるようになりました。
最終キーワードはreadFrom
およびwriteTo
メソッドから削除されました。
WILD_CARD
だけでなく、APPLICATION_JSON
の値がサポートされるメディア・タイプとして追加されました。