Oracle® Fusion Middleware

Oracle TopLinkソリューション・ガイド

12c (12.1.2)

E47993-02(原本部品番号:E28610-02)

2013年8月

このマニュアルでは、TopLinkの機能およびTopLinkの一般的な開発プロセスを示す、多くのシナリオ(ユースケース)を説明します。

Oracle Fusion Middleware Oracle TopLinkソリューション・ガイド, 12c (12.1.2)

E47993-02

Copyright © 2013, Oracle and/or its affiliates. All rights reserved.

このソフトウェアおよび関連ドキュメントの使用と開示は、ライセンス契約の制約条件に従うものとし、知的財産に関する法律により保護されています。ライセンス契約で明示的に許諾されている場合もしくは法律によって認められている場合を除き、形式、手段に関係なく、いかなる部分も使用、複写、複製、翻訳、放送、修正、ライセンス供与、送信、配布、発表、実行、公開または表示することはできません。このソフトウェアのリバース・エンジニアリング、逆アセンブル、逆コンパイルは互換性のために法律によって規定されている場合を除き、禁止されています。

ここに記載された情報は予告なしに変更される場合があります。また、誤りが無いことの保証はいたしかねます。誤りを見つけた場合は、オラクル社までご連絡ください。

このソフトウェアまたは関連ドキュメントが、米国政府機関もしくは米国政府機関に代わってこのソフトウェアまたは関連ドキュメントをライセンスされた者に提供される場合は、次のNoticeが適用されます。

U.S. GOVERNMENT RIGHTS Programs, software, databases, and related documentation and technical data delivered to U.S. Government customers are "commercial computer software" or "commercial technical data" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations. As such, the use, duplication, disclosure, modification, and adaptation shall be subject to the restrictions and license terms set forth in the applicable Government contract, and, to the extent applicable by the terms of the Government contract, the additional rights set forth in FAR 52.227-19, Commercial Computer Software License (December 2007). Oracle America, Inc., 500 Oracle Parkway, Redwood City, CA 94065.

このソフトウェアまたはハードウェアは様々な情報管理アプリケーションでの一般的な使用のために開発されたものです。このソフトウェアまたはハードウェアは、危険が伴うアプリケーション(人的傷害を発生させる可能性があるアプリケーションを含む)への用途を目的として開発されていません。このソフトウェアまたはハードウェアを危険が伴うアプリケーションで使用する際、このソフトウェアまたはハードウェアを安全に使用するために、適切な安全装置、バックアップ、冗長性(redundancy)、その他の対策を講じることは使用者の責任となります。このソフトウェアまたはハードウェアを危険が伴うアプリケーションで使用したことに起因して損害が発生しても、オラクル社およびその関連会社は一切の責任を負いかねます。

OracleおよびJavaはOracle およびその関連企業の登録商標です。その他の名称は、それぞれの所有者の商標または登録商標です。

Intel、Intel Xeonは、Intel Corporationの商標または登録商標です。すべてのSPARCの商標はライセンスをもとに使用し、SPARC International, Inc.の商標または登録商標です。AMD、Opteron、AMDロゴ、AMD Opteronロゴは、Advanced Micro Devices, Inc.の商標または登録商標です。UNIXはThe Open Groupの登録商標です。

このソフトウェアまたはハードウェアおよびドキュメントは、第三者のコンテンツ、製品、サービスへのアクセス、あるいはそれらに関する情報を提供することがあります。オラクル社およびその関連会社は、第三者のコンテンツ、製品、サービスに関して一切の責任を負わず、いかなる保証もいたしません。オラクル社およびその関連会社は、第三者のコンテンツ、製品、サービスへのアクセスまたは使用によって損失、費用、あるいは損害が発生しても、一切の責任を負いかねます。

目次

タイトルおよび著作権情報

はじめに

- 対象読者

- ドキュメントのアクセシビリティについて

- 関連ドキュメント

- 表記規則

このガイドで説明する新機能

- 12c (12.1.2)での新機能と変更された機能

- このガイドのその他の主な変更

1 概要

- 1.1 このガイドについて

- 1.2 このドキュメントで使用している用語

- 1.3 基礎的な必知事項

- 1.4 ユース・ケース

2 Oracle TopLinkのインストール

- 2.1 概要

- 2.2 タスク1: 前提条件

- 2.3 タスク2: TopLinkのダウンロード

- 2.4 タスク3: インストーラの実行

- 2.5 その他の参考資料

3 WebLogic ServerでのTopLinkの使用

- 3.1 ソリューションの概要

- 3.1.1 WebLogic ServerでTopLinkを使用する利点

- 3.1.2 TopLinkおよびその他のFusion Middleware製品

- 3.2 ソリューションの実装

- 3.2.1 タスク1: 前提条件

- 3.2.2 オプションのタスク: WebLogic ServerでのEclipseLinkのリリースの更新(オプション)

- 3.2.3 タスク3: WebLogic ServerのJMX MBean拡張の構成

- 3.2.4 タスク4: ロギング統合の使用または再構成

- 3.2.4.1 ロギング統合の動作方法

- 3.2.4.2 管理コンソールでの永続性ユニットのロギング・レベルの表示

- 3.2.4.3 デフォルト・ロギング統合のオーバーライド

- 3.2.4.4 EclipseLinkのロギングを公開するためのWebLogic Serverの構成

- 3.2.4.5 その他の考慮事項

- 3.2.5 タスク5: EclipseLinkを使用したJavaアプリケーションへの永続性の追加

- 3.2.6 タスク6: データ・ソースの構成

- 3.2.6.1 JPAアプリケーションのデータ・ソースを構成する方法

- 3.2.6.2 グローバル・スコープのJTAデータ・ソースの構成

- 3.2.6.3 アプリケーション・スコープのJTAデータ・ソースの構成

- 3.2.6.4 非JTAデータ・ソースの構成およびアプリケーションのトランザクション管理

- 3.2.6.5 設定の一致の確認

- 3.2.7 タスク7: Oracle Databaseの高度な機能を使用するためのドメインの拡張

- 3.2.8 タスク8: WebLogic Serverの起動とアプリケーションのデプロイ

- 3.2.9 タスク9: アプリケーションの実行

- 3.2.10 タスク10: WebLogic Serverの永続性設定の構成および監視

- 3.3 その他の参考資料

4 GlassFish ServerでのTopLinkの使用

- 4.1 ソリューションの概要

- 4.1.1 GlassFish ServerでTopLinkを使用する利点

- 4.1.2 Fusion Middleware製品に対するGlassFish ServerとTopLinkの関係

- 4.2 ソリューションの実装

- 4.2.1 タスク1: 前提条件

- 4.2.2 タスク2: GlassFish Serverのインストール

- 4.2.3 タスク3: データ・ソースの設定

- 4.2.3.1 GlassFish ServerへのOracleデータベースのJDBCドライバの統合

- 4.2.3.2 リソースに対するJDBC接続プールの作成

- 4.2.3.3 JDBCリソースの作成

- 4.2.4 タスク4: persistence.xmlファイルの作成

- 4.2.4.1 永続性プロバイダの指定

- 4.2.4.2 Oracleデータベースの指定

- 4.2.4.3 ロギングの指定

- 4.2.5 タスク5: JPA用のGlassFish Serverの設定

- 4.2.6 タスク6: アプリケーションの作成

- 4.2.7 タスク7: GlassFish Serverに対するアプリケーションのデプロイ

- 4.2.8 タスク8: アプリケーションの実行

- 4.2.9 タスク9: アプリケーションの監視

- 4.3 その他の参考資料

5 JBoss 7 Application ServerでTopLinkを使用する方法

- 5.1 ソリューションの概要

- 5.2 ソリューションの実装

- 5.2.1 タスク1: 前提条件

- 5.2.2 タスク2: JBossのモジュールとしてのEclipseLinkの構成

- 5.2.3 タスク3: JBossのモジュールとしてのojdbc6.jarの追加

- 5.2.4 タスク4: ドライバ定義およびデータ・ソースの作成

- 5.2.5 タスク5: ユーザーの作成

- 5.2.6 タスク6: JBossのプロパティの変更

- 5.2.7 タスク7: その他の要件

- 5.2.8 タスク8: JBossの起動

- 5.3 その他の参考資料

6 IBM WebSphere Application ServerでTopLinkを使用する方法

- 6.1 ソリューションの概要

- 6.2 ソリューションの実装

- 6.2.1 タスク1: 前提条件

- 6.2.2 タスク2: 永続性ユニットの構成

- 6.2.3 タスク3: EclipseLinkを使用するためのサーバーおよびアプリケーションの構成

- 6.2.3.1 EclipseLinkをグローバルで利用できるようにするためのサーバーの変更

- 6.2.3.2 アプリケーションEARへのEclipseLinkのパッケージ

- 6.2.3.3 WARへのEclipseLinkのパッケージ

- 6.3 その他の参考資料

7 Native TopLinkからの移行

- 7.1 ソリューションの概要

- 7.2 ソリューションの実装

- 7.2.1 タスク1: 前提条件

- 7.2.2 タスク2: 非推奨および削除されたネイティブAPIの置換

- 7.2.2.1 置換されたAPI

- 7.2.2.2 非推奨のAPI

- 7.2.2.3 削除されたAPI

- 7.2.2.4 その他のAPIの変更

- 7.2.3 タスク3: パッケージの名前変更

- 7.2.4 タスク4: XML構成ファイルの変換

- 7.2.4.1 セッションXML

- 7.2.4.2 デプロイメントXML

- 7.2.4.3 永続性XML

- 7.2.4.4 ORM XML

- 7.2.5 タスク5: Oracle TopLink Workbenchプロジェクトの変換(オプション)

- 7.3 その他の参考資料

8 HibernateからTopLinkへの移行

- 8.1 ソリューションの概要

- 8.2 主なタスク

- 8.2.1 タスク1: 前提条件

- 8.2.2 タスク1: Hibernateのエンティティ注釈の変換

- 8.2.2.1 SelectBeforeUpdate、dynamicInsertおよびdynamicUpdate属性の変換

- 8.2.2.2 OptimisticLock属性の変換

- 8.2.3 タスク2: Hibernateのカスタム・シーケンス・ジェネレータ注釈の変換

- 8.2.4 タスク3: Hibernateのマッピング注釈の変換

- 8.2.4.1 @ForeignKey注釈の変換

- 8.2.4.2 @Cache注釈の変換

- 8.2.5 タスク4: persistence.xmlファイルの変更

- 8.2.5.1 変更されたpersistence.xmlファイル

- 8.2.5.2 データベース表の削除および作成

- 8.2.5.3 データベース表の作成または拡張

- 8.2.6 タスク5: Hibernate APIからEclipseLink APIへの変換

- 8.3 その他の参考資料

9 コンポジット永続性ユニットによる複数データベースの使用

- 9.1 ソリューションの概要

- 9.1.1 コンポジット永続性ユニットの要件

- 9.2 ソリューションの実装

- 9.2.1 タスク1: コンポジット永続性ユニットの構成

- 9.2.2 タスク2: コンポジット永続性ユニットの使用

- 9.2.3 タスク3: コンポジット永続性ユニットのデプロイ

- 9.3 その他の参考資料

- 9.3.1 関連Javadoc

10 クラスタ内のアプリケーションのスケーリング

- 10.1 ソリューションの概要

- 10.2 ソリューションの実装

- 10.2.1 タスク1: キャッシュの整合性の構成

- 10.2.1.1 エンティティのキャッシュの無効化

- 10.2.1.2 キャッシュのリフレッシュ

- 10.2.1.3 エンティティのキャッシュの期限の設定

- 10.2.1.4 オプティミスティック・ロックの設定

- 10.2.1.5 キャッシュ・コーディネーションの使用

- 10.2.2 タスク2: EclipseLinkの有効化の確認

- 10.2.3 タスク3: すべてのアプリケーション・サーバーがクラスタ内にあることの確認

- 10.2.4 データのスケールのためのデータ・パーティション化の使用

- 10.2.4.1 クラスタ化されたデータベースおよびOracle RAC

- 10.3 その他の参考資料

11 Software as a Serviceの提供

- 11.1 ソリューションの概要

12 JPAエンティティおよびJAXB Beanの拡張可能化

- 12.1 JPAエンティティの拡張可能化

- 12.1.1 拡張可能なJPAエンティティを作成およびサポートするための主要タスク

- 12.1.1.1 タスク1: エンティティの構成

- 12.1.1.2 タスク2: スキーマの設計

- 12.1.1.3 タスク3: 追加マッピングの提供

- 12.1.1.4 タスク4: MetaDataSourceを使用した拡張の外部化

- 12.1.2 コード例

- 12.2 JAXB Beanの拡張可能化

- 12.2.1 主な手順

- 12.2.1.1 タスク1: Beanの構成

- 12.2.1.2 タスク2: 追加マッピングの提供

- 12.2.2 コード例

- 12.2.2.1 基本設定

- 12.2.2.2 テナントの定義

- 12.3 その他の参考資料

13 外部のメタデータ・ソースの使用

- 13.1 ソリューションの概要

- 13.2 eclipselink-orm.xmlファイルの外部使用

- 13.3 主なタスク

- 13.3.1 タスク1: 永続性ユニットの構成

- 13.3.2 タスク2: サーバーの構成

- 13.4 その他の参考資料

14 TopLinkを使用したテナントの分離

- 14.1 ソリューションの概要

- 14.2 単一表マルチテナントの使用

- 14.2.1 単一表マルチテナントを使用する場合の主なタスク

- 14.2.1.1 タスク1: 前提条件

- 14.2.1.2 タスク2: 単一表マルチテナントの有効化

- 14.2.1.3 タスク3: テナント識別子列の指定

- 14.2.1.4 コンテキスト・プロパティおよびキャッシュ範囲の構成

- 14.2.1.5 タスク4: 操作および問合せの実行

- 14.2.1.6 タスク5: 継承階層での単一表マルチテナントの使用

- 14.3 テナントごとの表マルチテナントの使用

- 14.3.1 テナントごとの表マルチテナントを使用する場合の主なタスク

- 14.3.1.1 タスク1: 前提条件

- 14.3.1.2 タスク2: テナントごとの表マルチテナントの有効化

- 14.3.1.3 タスク3: テナント表識別子の指定

- 14.3.1.4 タスク4: 実行時のコンテキスト・プロパティの指定

- 14.3.1.5 タスク5: 操作および問合せの実行

- 14.4 VPDマルチテナントの使用

- 14.4.1 VPDマルチテナントを使用する場合の主なタスク

- 14.4.1.1 タスク1: 前提条件

- 14.4.1.2 タスク2: 仮想プライベート・データベースの構成

- 14.4.1.3 タスク3: エンティティまたはマップ済スーパークラスの構成

- 14.4.1.4 タスク4: 基準生成の無効化

- 14.4.1.5 タスク5: persistence.xmlの構成

- 14.5 その他の参考資料

15 XMLへのJPAのマッピング

- 15.1 ソリューションの概要

- 15.1.1 XMLバインディングの理解

- 15.1.2 JAXBの理解

- 15.1.3 MOXyの理解

- 15.1.4 XMLデータ表現の理解

- 15.2 XMLへのJPAエンティティのバインディング

- 15.2.1 XMLへのJPAリレーションシップのバインディング

- 15.2.1.1 タスク1: アクセッサ・タイプの定義およびクラスのインポート

- 15.2.1.2 タスク2: 私有のリレーションシップのマッピング

- 15.2.1.3 タスク3: 共有参照リレーションシップのマッピング

- 15.2.1.4 JPAエンティティ

- 15.2.2 XMLへの複合主キーのバインディング

- 15.2.2.1 タスク1: XMLアクセッサ・タイプの定義

- 15.2.2.2 タスク2: ターゲット・オブジェクトの作成

- 15.2.2.3 タスク3: ソース・オブジェクトの作成

- 15.2.3 XMLへの埋込みIDクラスのバインディング

- 15.2.3.1 タスク1: XMLアクセッサ・タイプの定義

- 15.2.3.2 タスク2: ターゲット・オブジェクトの作成

- 15.2.3.3 タスク3: ソース・オブジェクトの作成

- 15.2.3.4 タスク5: PhoneNumberCustomizerクラスとしてのDescriptorCustomizerの実装

- 15.2.4 EclipseLinkのXMLバインディング文書の使用

- 15.3 XMLテキスト・ノードへの単純なJava値のマッピング

- 15.3.1 属性に対する値のマッピング

- 15.3.1.1 Javaオブジェクトからのマッピング

- 15.3.1.2 OXMメタデータ形式でのマッピングの定義

- 15.3.2 テキスト・ノードへの値のマッピング

- 15.3.2.1 単純なテキスト・ノードに対する値のマッピング

- 15.3.2.2 単純な順序でのテキスト・ノードへの値のマッピング

- 15.3.2.3 サブ要素のテキスト・ノードに対する値のマッピング

- 15.3.2.4 位置によるテキスト・ノードへの値のマッピング

- 15.4 XMLメタデータ表現を使用したJAXB注釈のオーバーライド

- 15.4.1 タスク1: XMLでの高度なマッピングの定義

- 15.4.2 タスク2: JAXBContextの使用方法の構成

- 15.4.3 タスク3: JAXB実装としてのMOXyの指定

- 15.5 マッピングに対するXPath述語の使用

- 15.5.1 XPath述語の理解

- 15.5.2 位置に基づくマッピング

- 15.5.3 属性値に基づくマッピング

- 15.5.3.1 タスク1: Customerエンティティの作成

- 15.5.3.2 タスク2: Addressエンティティの作成

- 15.5.3.3 タスク3: PhoneNumberエンティティの作成

- 15.5.4 セルフ・マッピング

- 15.6 動的JAXB/MOXyの使用

- 15.6.1 タスク1: XMLスキーマからの動的JAXBContextのブートストラップ

- 15.6.1.1 XMLスキーマからのブートストラップ

- 15.6.1.2 XMLスキーマ

- 15.6.1.3 スキーマのインポート/インクルードの処理

- 15.6.1.4 EntityResolverを実装して渡す方法

- 15.6.1.5 エラー処理

- 15.6.1.6 ClassLoaderの指定

- 15.6.2 タスク2: 動的エンティティの作成とXMLへのマーシャル

- 15.6.2.1 動的エンティティの作成

- 15.6.2.2 XMLへの動的エンティティのマーシャリング

- 15.6.3 タスク3: XMLからの動的エンティティのアンマーシャル

- 15.6.3.1 XMLからの動的エンティティのアンマーシャル

- 15.6.3.2 動的エンティティからのデータの取得

- 15.6.3.3 DynamicTypeを使用した、動的エンティティのイントロスペクション

- 15.7 その他の参考資料

16 JSONドキュメントからのオブジェクトの変換

- 16.1 ソリューションの概要

- 16.2 ソリューションの実装

- 16.2.1 タスク1: JSONドキュメントのマーシャリングおよびアンマーシャリング

- 16.2.2 タスク2: JSONバインディングの指定

- 16.2.3 タスク3: JSONデータ型の指定

- 16.2.4 タスク4: 属性のサポート

- 16.2.5 タスク5: ルート要素の非サポート

- 16.2.6 タスク5 名前空間の使用

- 16.2.7 タスク6: コレクションの使用

- 16.2.8 タスク7: ルートレベル・コレクションのマッピング

- 16.2.9 タスク8: テキスト値のラッピング

- 16.3 その他の参考資料

17 コンテナ外部のJPAのテスト

- 17.1 JPAデプロイメントの理解

- 17.1.1 EntityManagerの使用

- 17.2 persistence.xmlファイルの構成

- 17.2.1 主なタスク

- 17.2.1.1 タスク1: persistence.xmlファイルの使用

- 17.2.1.2 タスク2: EntityManagerFactoryのインスタンス化

- 17.3 プロパティ・マップの使用

- 17.3.1 主なタスク

- 17.3.1.1 タスク1: persistence.xmlファイルの構成

- 17.3.1.2 タスク2: ブートストラップAPIの構成

- 17.3.1.3 タスク3: EntityManagerFactoryのインスタンス化

- 17.4 ウィービングの使用

- 17.4.1 Java SE環境でのウィービングの無効化および有効化

- 17.4.2 Java EE環境でのウィービングの無効化および有効化

- 17.5 その他の参考資料

- 17.5.1 関連Javadoc

18 パフォーマンスの向上

- 18.1 パフォーマンス機能

- 18.1.1 オブジェクト・キャッシング

- 18.1.1.1 キャッシング注釈

- 18.1.1.2 @Cache注釈の使用

- 18.1.2 問合せ

- 18.1.2.1 読取り専用問合せ

- 18.1.2.2 結合フェッチ

- 18.1.2.3 バッチ読取り

- 18.1.2.4 フェッチ・サイズ

- 18.1.2.5 ページ区切り

- 18.1.2.6 キャッシュの使用方法

- 18.1.3 マッピング

- 18.1.3.1 読取り専用オブジェクト

- 18.1.3.2 ウィービング

- 18.1.4 トランザクション

- 18.1.5 データベース

- 18.1.5.1 接続プーリング

- 18.1.5.2 パラメータ化されたSQLとSQL文のキャッシュ

- 18.1.5.3 バッチ書込み

- 18.1.6 ツール

- 18.2 EclipseLinkが有効なアプリケーションを監視および最適化

- 18.2.1 パフォーマンス最適化の推奨事項およびヒント

- 18.2.2 タスク1: EclipseLinkプロファイラを使用したEclipseLinkのパフォーマンスの測定

- 18.2.2.1 EclipseLinkプロファイラの有効化

- 18.2.2.2 プロファイラの結果へのアクセスおよび解釈

- 18.2.3 タスク2: アプリケーションのパフォーマンス問題の原因特定

- 18.2.4 タスク3: パフォーマンスが悪いアプリケーション・コンポーネントの変更

- 18.2.4.1 一般的なパフォーマンスの最適化の識別

- 18.2.4.2 スキーマ

- 18.2.4.3 マッピングおよびディスクリプタ

- 18.2.4.4 キャッシュ

- 18.2.4.5 データ・アクセス

- 18.2.4.6 問合せ

- 18.2.4.7 アプリケーション・サーバーとデータベースの最適化

- 18.2.5 タスク4: パフォーマンスの再測定

19 TopLink GridでのOracle Coherenceを使用したアプリケーションのスケーリング

- 19.1 ソリューションの概要

- 19.2 ソリューションの実装

- 19.3 その他の参考資料

20 RESTfulデータ・サービスを介したJPAエンティティの公開

- 20.1 ソリューションの概要

- 20.2 ソリューションの実装

- 20.2.1 手順1: 前提条件

- 20.2.2 手順2: アプリケーションの作成および構成

- 20.2.3 手順3: RESTfulデータ・サービスのURIの基本の理解

- 20.2.4 手順4: JPA、JAXBまたはJSONを使用したエンティティの表現

- 20.2.4.1 リレーションシップ

- 20.2.5 手順5: 永続性ユニットに対する操作用のクライアント呼び出しの発行

- 20.2.5.1 ヘッダー内でのメディア形式の指定

- 20.2.5.2 ロギングについて

- 20.2.6 手順6: セキュリティの実装

- 20.2.7 手順7: RESTfulデータ・サービスの応答の構造の理解

- 20.2.7.1 基本データ型

- 20.2.7.2 リンクおよびリレーションシップ

- 20.3 その他の参考資料

- 20.4 RESTfulデータ・サービスのAPIリファレンス

- エンティティ操作

- FIND

- PERSIST

- MERGE

- DELETE

- リレーションシップに対するエンティティ操作

- READ

- ADD

- REMOVE

- 問合せ操作

- 結果を返す問合せ一覧

- 更新/削除の問合せ

- 単一リクエスト問合せ

- 基本操作

- 既存の永続性ユニットの列挙

- メタデータ操作

- 永続性ユニットのタイプの列挙

- 永続性ユニットの問合せの列挙

- 特定のエンティティの説明

21 TopLinkライブ・データ問合せを使用したデータの更新

- 21.1 ソリューションの概要

- 21.1.1 Oracle Database CQNの概要およびTopLinkのキャッシュのトラッキング

- 21.1.2 TopLinkライブ・データ問合せの作成および使用

- 21.2 ソリューションの実装

- 21.2.1 手順1: 前提条件

- 21.2.2 手順2: データベース権限の付与

- 21.2.3 手順3: ライブ・データ問合せおよびCQNサブスクリプションの作成

- 21.3 その他の参考資料

22 キャッシュを無効にするためのデータベース・イベントの使用

- 22.1 ソリューションの概要

- 22.2 ソリューションの実装

- 22.2.1 タスク1: データベースおよび表の設定

- 22.2.2 タスク2: ユーザー権限の付与

- 22.2.3 タスク3: クラスパスの設定

- 22.2.4 タスク4: 変更通知に参加するクラスの識別

- 22.2.5 タスク5: データベース・イベント・リスナーの追加

- 22.2.6 タスク6: Javaファイルの編集

- 22.2.6.1 オプティミスティック・ロックの設定

- 22.2.6.2 変更通知からのクラスの除外(オプション)

- 22.2.6.3 セカンダリ表での変更追跡(オプション)

- 22.3 ソリューションの制限

- 22.4 その他の参考資料

23 NoSQLデータベースでTopLinkを使用する方法

- 23.1 ソリューションの概要

- 23.2 ソリューションの実装

- 23.2.1 タスク1: データのマッピング

- 23.2.2 タスク2: IDの定義

- 23.2.3 タスク3: マッピングの定義

- 23.2.4 タスク4: ロックの使用

- 23.2.5 タスク5: 問合せの定義

- 23.2.5.1 JPQL問合せ

- 23.2.5.2 ネイティブ問合せ

- 23.2.6 タスク6: データベースへの接続

- 23.3 その他の参考資料

24 Oracle DatabaseでOracle TopLinkを使用する方法

- 24.1 ソリューションの概要

- 24.2 ソリューションの実装

- 24.2.1 Oracleプラットフォームに固有のAPIの使用

- 24.2.2 EclipseLinkでのOracle PL/SQLの使用

- 24.2.2.1 Oracle PL/SQLストアド関数の実行

- 24.2.2.2 Oracleストアド・プロシージャでのPL/SQL引数の処理

- 24.2.3 Oracle仮想プライベート・データベースの使用

- 24.2.4 Oracleプロキシ認証の使用

- 24.2.4.1 主なタスク

- 24.2.4.2 キャッシュおよびセキュリティ

- 24.2.4.3 行レベルのセキュリティのためのOracle仮想プライベート・データベースの使用

- 24.2.5 Oracle RACでのEclipseLinkの使用

- 24.2.5.1 Java EEアプリケーションからのRACが有効なデータベースへのアクセス

- 24.2.5.2 スタンドアロン・アプリケーションからのRACが有効なデータベースへの接続

- 24.2.6 Oracle Spatial and Graphの使用

- 24.3 その他の参考資料

はじめに

Eclipse Foundationが提供するオープン・ソースの永続性フレームワークであるEclipseLinkによりコア機能が提供されるOracle TopLinkは、パフォーマンス、スケーラビリティ、開発者の生産性、アーキテクチャと設計の柔軟性の高さにおいて、リレーショナル、XMLおよびJSONの永続化のすべてのニーズに応える、標準に基づいたエンタープライズJavaソリューションです。

対象読者

様々なエンジニアがTopLinkを使用しています。TopLinkのユーザーは、(たとえばJava Persistence APIなど)TopLinkに関連するテクノロジおよびサービスの使用に習熟している必要があります。このガイドでは、関連する一般的なタスクの詳細は説明せず、TopLinkの機能を中心に説明します。

このガイドの対象読者は次のとおりです。

- 永続性サービスの次のテクノロジのいずれかを使用してアプリケーションを開発する開発者。

- Java Persistence API (JPA) 2.nとEclipseLink JPAの拡張

- Java Architecture for XML Binding 2.n (JAXB)とEclipseLink Object-XMLの拡張

- EclipseLinkデータベースWebサービス(DBWS)

開発者は、Java Platform, Standard Edition (Java SEプラットフォーム)、Java Platform、Enterprise Edition (Java EEプラットフォーム)の概念およびプログラミング手法に精通している必要があります。.

EclipseLink JPAを使用する開発者は、http://jcp.org/en/jsr/detail?id=338のJava Persistence Architecture 2.1仕様に定義されているJPA 2.1の概念およびプログラミング技法を十分に理解している必要があります。

EclipseLink Object-XMLを使用する開発者は、http://jcp.org/aboutJava/communityprocess/pfd/jsr222/index.htmlのJava Architecture for XML Binding 2.0仕様に定義されているJAXB 2.0の概念およびプログラミング技法を十分に理解している必要があります。

EclipseLink DBWSを使用する開発者は、http://jcp.org/aboutJava/communityprocess/pfd/jsr222/index.htmlのJava API for XML-Based Web Services 2.0仕様に定義されているJAX-WS 2.0の概念およびプログラミング技法を十分に理解している必要があります。

- TopLinkの永続性テクノロジを使用して、アプリケーションをデプロイおよび管理する管理者およびデプロイヤ。これらのユーザーは、選択したアプリケーション・サーバーの基本的な操作を十分に理解している必要があります。

ドキュメントのアクセシビリティについて

Oracleのアクセシビリティについての詳細情報は、Oracle Accessibility ProgramのWebサイト(http://www.oracle.com/pls/topic/lookup?ctx=acc&id=docacc)を参照してください。

Oracleサポートへのアクセス

Oracleカスタマは、My Oracle Supportから電子サポートにアクセスできます。詳細は、http://www.oracle.com/pls/topic/lookup?ctx=acc&id=infoまたはhttp://www.oracle.com/pls/topic/lookup?ctx=acc&id=trs (聴覚障害者向け)を参照してください。

関連ドキュメント

詳細は、次のドキュメントを参照してください。

- 『Oracle TopLinkの理解』

- 『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』

- 『Oracle TopLink Database Webサービスによる永続性アーキテクチャの開発』

- 『Oracle TopLinkによるJAXBアプリケーションの開発』

- 『Oracle TopLink Java APIリファレンス』

- EclipseLink Documentation Center (http://www.eclipse.org/eclipselink/documentation/)

- 『Oracle Coherenceの統合』

- 『Oracle TopLinkリリース・ノート』

表記規則

このマニュアルでは次の表記規則を使用します。

規則

意味

太字

太字は、操作に関連するGraphical User Interface要素、または本文中で定義されている用語および用語集に記載されている用語を示します。

イタリック体

イタリックは、ユーザーが特定の値を指定するプレースホルダ変数を示します。

固定幅フォント

固定幅フォントは、段落内のコマンド、URL、サンプル内のコード、画面に表示されるテキスト、または入力するテキストを示します。

太字の等幅フォント

太字の等幅フォント・タイプは、特定の項目を強調するためにコード例で使用されています。

このガイドで説明する新機能

次のトピックでは、Oracle Toplinkの新機能と変更機能およびこのガイドで説明する主な変更について紹介し、その他の参考資料へのリンクを示します。このマニュアルは、以前Oracle TopLinkソリューション・ガイドと呼ばれていたマニュアルの新しいエディションです。

12c (12.1.2)での新機能と変更された機能

Oracle TopLink 12c (12.1.2)には、このマニュアルに記載されている次の新機能および機能変更があります。このリストには、このリリースの新機能または変更された機能をすべては含んでいません。このマニュアルに記載されている新機能のみが含まれます。

- 既存のOracleホームを含む希望の場所にTopLinkをインストールするクイック・インストーラ。第2章「Oracle TopLinkのインストール」を参照してください。

- 複数のアプリケーション・テナントがデータベース表やスキーマを共有する場合のクライアントの分離。これによりアプリケーションでは、同じアプリケーションの複数のテナントのエンティティを管理できます。第14章「TopLinkを使用したテナントの分離」を参照してください。

- JavaScript Object Notation (JSON)から直接オブジェクトを変更するJSON結合。これは、Java API for RESTful Web Services (JAX-RS)サービスでJSONメッセージを使用しRESTfulサービスを作成する際に便利です。第16章「JSONドキュメントからのオブジェクトの変換」を参照してください。

- JSONまたはXMLメディアのいずれかを使用するJAX-RSなどの標準に基づくRESTfulサービスを介してJava Persistence API (JPA)エンティティを公開するRESTful永続性。第20章「RESTfulデータ・サービスを介したJPAエンティティの公開」を参照してください。

- ライブ問合せによってバッキング・データ・ストアの変更が追跡されるTopLinkライブ・データ問合せ(ライブ問合せ)。第21章「TopLinkライブ・データ問合せを使用したデータの更新」を参照してください。

- キャッシュされたオブジェクトが共有キャッシュで無効化できるように、データベースがデータベースの変更をTopLinkに通知するOracle Database連続問合せ通知(CQN)に対するサポート。第22章「キャッシュを無効にするためのデータベース・イベントの使用」を参照してください。

- NoSQLデータベースに対する非リレーショナル(NoSQL)データ・ソースへのマッピングのサポート。第23章「NoSQLデータベースでTopLinkを使用する方法」を参照してください。

このリリースの変更の全一覧については、http://www.oracle.com//toplink/を参照してください。

このマニュアルに記載されているその他の重要な変更

12c (12.1.2)でこのガイドは何箇所か更新されています。次の表に、追加または変更された項を示します。

- インストール情報が、付録から第2章「Oracle TopLinkのインストール」に移動され、古い情報は新しいクイック・インストーラの情報に置き換えられました。

- 第5章「JBoss 7 Application ServerでのTopLinkの使用」という新しい章が、JBoss Application Server 7.1にデプロイされたアプリケーションでTopLinkをどのように使用するか説明するために追加されました。

- 第6章「IBM WebSphere Application ServerでのTopLinkの使用」という新しい章が、IBM WebSphere Application ServerにデプロイしたアプリケーションでTopLinkをどのように使用するか説明するために追加されました。

- 第7章「ネイティブTopLinkからの移行」という新しい章が、TopLink 11g,リリース1 (11.1.1)以上でTopLinkのコア・ライブラリとなった、現在のEclipseLink APIに、ネイティブTopLinkオブジェクト・リレーショナル・マッピング(ORM) APIを使用しているアプリケーションを移行する方法を説明するために追加されました。

- 第10章「クラスタ内のアプリケーションのスケーリング」が、データのパーティション化を説明するために追加されました。

- 第11章「Software as a Serviceの提供」が4つの章に分割されました。

- 第11章「Software as a Serviceの提供」では、次の3つの章の概要のみを示しています。

- 第12章「JPAエンティティおよびJAXB Beanの拡張可能化」

- 第13章「外部メタデータ・ソースの使用」

- 第14章「TopLinkを使用したテナントの分離」(この章には、仮想プライベート・データベース(VPD)のマルチテナントおよびテナントごとの表マルチテナントに関する情報も含まれています)。

- 第16章「JSONドキュメントからのオブジェクトの変換」という新しい章が、JSONからまたJSONに直接オブジェクトを変換する方法を説明するために追加されました。

- 第17章「コンテナ外部のJPAのテスト」に、ウィービングに関する情報を、コンテナの外のアプリケーション(たとえば、Java Platform, Standard Edition (Java SEプラットフォーム)のアプリケーション)をテストするために永続性ユニットのJARファイルを使用する方法を説明するために追加されました。

- 第19章「TopLink GridでのOracle Coherenceを使用したアプリケーションのスケーリング」という新しい章が、高可用性の実現およびパフォーマンスの向上のためにアプリケーションでTopLink Gridを使用する方法を説明するために追加されました。

- 第20章「RESTfulデータ・サービスを介したJPAエンティティの公開」という章が、JSONまたはXMLメディアのいずれかを使用して、Java Persistence API-RESTful Services (JPA-RS)を介してJPAエンティティを公開する方法を説明するために追加されました。

- 第21章「TopLinkライブ・データ問合せを使用したデータの更新」という新しい章が、バッキング・データ・ストアに対する変更をトラッキングするためにTopLinkライブ問合せを使用する方法を説明するために追加されました。

- 第22章「キャッシュを無効にするためのデータベース・イベントの使用」という新しい章が、JPA環境でキャッシュを共有するためにEclipseLinkデータベース変更通知(DCN)の使用方法を説明するために追加されました。データベースはDCNにより、EclipseLinkにデータベースの変更を通知できるようになります。変更されたオブジェクトは、EclipseLinkの共有キャッシュでは無効になります。失効したデータは、他のアプリケーションがデータベース内の同じデータにアクセスする場合でも破棄されます。

- 第24章「Oracle DatabaseでOracle TopLinkを使用する方法」という新しい章が、TopLinkでサポートされるOracle Databaseの機能を使用する方法を説明するために追加されました。

1 概要

Oracle TopLinkは、Javaオブジェクトをリレーショナル・データベースやNoSQLデータベースなどのデータ・ストアにストアしたり、JavaオブジェクトをXMLまたはJSON文書に変換する、強力で柔軟なJava永続性フレームワークです。TopLinkでは、Java Platform, Standard Edition (Java SEプラットフォーム)およびJava Platform, Enterprise Edition (Java EEプラットフォーム)アプリケーションに永続性レイヤーを実装するAPIおよびランタイム環境が提供されます。

TopLinkのコア機能は、オープン・ソースのEclipse Foundationの永続性フレームワークであるEclipseLinkによって提供されています。EclipseLinkでは、Java Persistence API (JPA)、Java Architecture for XML Binding (JAXB)、および標準に基づいたその他の永続性テクノロジと、それらの標準の拡張が実装されます。TopLinkには、EclipseLinkがすべて含まれ、加えEclipseLink JPAとOracle Coherenceのキャッシュを統合するOracle TopLink Gridなどのその他の機能が含まれます。

EclipseLinkプロジェクトの詳細は、http://www.eclipse.org/eclipselink/のEclipse Persistence Services Project (EclipseLink)ホームを参照してください。

1.1 このガイドについて

この『Oracle TopLinkソリューション・ガイド』では、TopLinkの機能および一般的な開発プロセスを示す、多数のシナリオまたはユース・ケースを説明します。これらは、プロジェクトを完了するために必要なすべてのタスクを順を追って説明するチュートリアルではありません。このドキュメントでは、特定の問題を解決するための概略プロセスおよび重要な部分のみの詳細を説明し、さらに詳細を説明する他のドキュメントへのリンクを示しています。

1.2 このドキュメントで使用している用語

Oracle TopLinkおよびTopLinkは、含まれるすべてのEclipseLinkライブラリ、機能およびAPIとその他のOracle機能を加えた完全なOracle製品を意味します。このドキュメントでOracle TopLinkおよびTopLinkという名称は、製品全体についておよび特にOracleのみの機能について言及する場合に一般的に使用しています。EclipseLinkは、TopLinkに含まれるEclipseLink機能について言及する場合に使用しています。

1.3 基礎的な必知事項

このマニュアルを利用するには、次のことをすでによく理解している必要があります。

- Java SEプラットフォームおよびJava EEプラットフォームの概念およびプログラミング技法。TopLinkの現在のリリースでは、Java EE 6がサポートされています。詳細は、次を参照してください。
Java

- Javaのホーム・ページ: http://www.oracle.com/us/technologies/java/index.html

- Java EE 5のチュートリアル: http://download.oracle.com/javaee/5/tutorial/doc/bnbpy.html

- Java EE 6のチュートリアル: http://download.oracle.com/javaee/6/tutorial/doc/bnbpy.html

- Javaに関する多数の書籍およびWebサイト。

Oracle Java EEアプリケーション・サーバー

- Oracle WebLogic Serverのホーム・ページ: http://www.oracle.com/technetwork/middleware/weblogic/overview/index.html

- Oracle GlassFish Serverのホーム・ページ: http://www.oracle.com/technetwork/middleware/glassfish/overview/index.html

Oracle Java EE統合開発環境

- Oracle JDeveloper: http://www.oracle.com/technetwork/developer-tools/jdev/overview/index.html

- Oracle Enterprise Pack for Eclipse: http://www.oracle.com/technetwork/developer-tools/eclipse/overview/index.html

- EclipseLink JPAを使用して作業する場合は、http://jcp.org/aboutJava/communityprocess/final/jsr317/index.htmlのJava Persistence 2.0標準に定義されているJPA 2.0の概念およびプログラミング技法をよく理解している必要があります。

- EclipseLink JAXBを使用して作業する場合は、http://jcp.org/en/jsr/detail?id=222のJava Architecture for XML Binding (JAXB) 2.0標準に定義されているJAXB 2.0の概念およびプログラミング技法をよく理解している必要があります。

- JSONデータ交換形式を使用して作業する場合は、http://www.json.org/のJSONの概念およびプログラミング技法をよく理解している必要があります。XMLの詳細は、http://www.w3.org/XML/を参照してください。

- EclipseLink DBWSを使用して作業する場合は、http://jcp.org/en/jsr/detail?id=224の「API for XML-Based Web Services (JAX-WS) 2.0」に定義されているJAX-WS 2.0の概念およびプログラミング技法をよく理解している必要があります。

- REpresentational State Transfer (REST)サービスを使用して作業する場合は、http://jcp.org/en/jsr/detail?id=311の「JSR 311: JAX-RS: The Java API for RESTful Web Services」に定義されているRESTの概念およびプログラミング技法をよく理解している必要があります。

1.4 ユース・ケース

このガイドでは、次のユース・ケースが説明されています。

- 第2章「Oracle TopLinkのインストール」: スタンドアロンのTopLinkをダウンロードおよびインストールする方法。

- 第3章「WebLogic ServerでのTopLinkの使用」: WebLogic ServerでTopLinkを使用する方法。

- 第4章「GlassFish ServerでのTopLinkの使用」: GlassFish ServerでTopLinkを使用する方法。

- 第5章「JBoss 7 Application ServerでのTopLinkの使用」: JBoss 7 Application ServerでTopLinkを使用する方法。

- 第6章「IBM WebSphere Application ServerでのTopLinkの使用」: IBM WebSphere Application ServerでTopLinkを使用する方法。

- 第7章「ネイティブTopLinkからの移行」: ネイティブTopLinkオブジェクト・リレーショナル・マッピング(ORM) APIの使用から現在のEclipseLink APIの使用へアプリケーションを移行する方法。

- 第8章「HibernateからTopLinkへの移行」: Hibernate JPAの使用からEclipseLink JPAの使用へアプリケーションを移行する方法。

- 第9章「コンポジット永続性ユニットによる複数データベースの使用」: 複数の永続性ユニット(エンティティ・タイプの独自のセットがそれぞれに指定されている)を単一の永続性コンテキストとして公開する方法。

- 第10章「クラスタ内のアプリケーションのスケーリング」: クラスタ化されたアプリケーション・サーバー環境でスケーラビリティを確保しながらEclipseLinkアプリケーションを構成する方法。

- 第11章「Software as a Serviceの提供」: TopLinkのSoftware as a Service (SaaS)機能の概要。

- 第12章「JPAエンティティおよびJAXB Beanの拡張可能化」: JPAエンティティまたはJAXB Beanを拡張可能にする方法。

- 第13章「外部メタデータ・ソースの使用」: 外部メタデータ・ソースの使用方法。

- 第14章「TopLinkを使用したテナントの分離」: 表およびスキーマを含むデータ・ソースを共有するアプリケーションで複数のテナントをサポートする方法。

- 第15章「XMLへのJPAのマッピング」: EclipseLink JAXBを使用して、JPAエンティティをXMLにマップする方法。

- 第17章「コンテナ外部のJPAのテスト」: コンテナ外部のEclipseLinkアプリケーションをテストする方法。

- 第18章「パフォーマンスの拡張」: TopLinkで最高のパフォーマンスを得る方法。

- 第19章「TopLink GridでのOracle Coherenceを使用したアプリケーションのスケーリング」: TopLink Gridを使用して可用性を高め、パフォーマンスを向上させる方法。

- 第20章「RESTfulデータ・サービスを介したJPAエンティティの公開」: EclipseLinkのJava Persistence API for RESTful Services (JPA-RS)を使用してRESTfulサービスを介してエンティティを公開する方法。

- 第21章「TopLinkライブ・データ問合せを使用したデータの更新」: TopLinkライブ問合せを使用してバッキング・データ・ストアに対する変更を追跡する方法。

- 第22章「キャッシュを無効にするためのデータベース・イベントの使用」: JPAの共有データベースで、EclipseLinkデータベース変更通知(DCN)を使用してキャッシングを実行する方法。

- 第23章「NoSQLデータベースでTopLinkを使用する方法」: EclipseLinkで非リレーショナル(非SQL)データ・ソースにオブジェクトをマップする方法。

2 Oracle TopLinkのインストール

この章では、Oracle TopLinkのインストール方法を説明します。

次の手順では、ダウンロード・サイトより入手できるjarファイルのクイック・インストーラを使用してTopLinkをインストールする方法を説明します。zipファイルでも用意されています。クイック・インストーラではなくzipファイルを使用してインストールする場合は、zipファイルに含まれるreadmeファイルの手順に従ってください。

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

- 2.1項「概要」

- 2.2項「タスク1: 前提条件」

- 2.3項「タスク2: TopLinkのダウンロード」

- 2.4項「タスク3: インストーラの実行」

- 2.5項「その他の参考資料」

2.1 概要

TopLinkには、Oracle WebLogic Server、Glassfish Server、Oracle JDeveloperおよびOracle CoherenceなどのいくつかのOracle製品が統合されています。TopLinkは、スタンドアロンでの配布をダウンロードして、他のアプリケーション・サーバーと統合し、アプリケーションの永続プロバイダ性として使用することもできます。この章では、スタンドアロン配布のインストール方法を説明します。

2.2 タスク1: 前提条件

現在のTopLinkのバージョンの完全な製品要件の一覧および最新の動作要件に関する情報は、次を参照してください。

http://www.oracle.com/technetwork/middleware/ias/index-099524.html

TopLinkには、JDK 1.6 (またはそれ以降)と互換性のあるJava Virtual Machine (JVM)が必要です。また、TopLinkではURLベースのスキーマおよびホストにあるドキュメントを使用するためのインターネット・アクセスも必要です。

2.3 タスク2: TopLinkのダウンロード

別のOracleのダウンロードには含まれないTopLinkの配布をダウンロードするには、次の手順を実行します。

1. http://www.oracle.com/technetwork/middleware/toplink/downloads/index.htmlのTopLinkのダウンロード・ページに移動します。

2. 「ライセンス契約に同意する」を選択し、ライセンス契約に同意します。

3. 希望のTopLinkのバージョンを探し、コンピュータにダウンロードします。
TopLink 12cリリース1 (12.1.2)以降、TopLinkはtoplink_quick_121200.jarという名前のJavaクイック・インストーラとして提供されています。この手順では、そのクイック・インストーラを使用したインストール手順を説明します。

これは、任意のディレクトリにダウンロードできます。

2.4 タスク3: インストーラの実行

TopLinkは、任意のディレクトリにインストールできます。クイック・インストーラを実行します。

1. たとえば、C:\toplinkなど、TopLinkをインストールするディレクトリを作成します。ディレクトリは完全に空である必要があります。

2. 新しいディレクトリにコマンド・ウィンドウを開きます。

3. jarファイルを解凍する次のコマンドを実行します。

- 有効なJREまたはJDKがパスにある場合、次を実行します。
java -jar path\toplink_quick_121200.jar

ここでpath\は、JARファイルをダウンロードしたディレクトリへのパスです。

たとえば、新しい空のC:\toplinkディレクトリを作成してJARファイルをc:\downloadsにダウンロードした場合、次を実行します。

C:\toplink>java -jar c:\downloads\toplink_quick_121200.jar

- 有効なJREまたはJDKがパスにない場合、または具体的に使用したいものがある場合、次を実行します。
JAVA_HOME\java -jar path\toplink_quick_121200.jar

ここで、JAVA_HOMEは、Javaランタイムを含むディレクトリです。たとえば、ランタイムがC:\java\jdk1.6.0_33\bin\にある場合、次を実行します。

C:\toplink>c:\java\jdk1.6.0_33\bin\java -jar c:\downloads\toplink_quick_121200.jar

TopLinkライブラリ、スキーマ、ユーティリティ、ドキュメントは、インストールで作成されたディレクトリ構造のTOPLINK_HOME\oracle_common\modules\oracle.toplink_version_noおよびTOPLINK_HOME\toplinkにあります。

2.5 その他の参考資料

この章のソリューションが実装されているその他のテクノロジおよびツールの詳細は、次を参照してください。

- TopLinkおよびその他のOracle Fusion Middleware製品のインストールにMavenを使用する方法の詳細は、『Oracle Fusion Middleware継続的インテグレーションによるアプリケーションの開発』を参照してください。

- Oracle WebLogic Serverのインストールの詳細は、『Oracle WebLogic ServerおよびCoherenceのインストールと構成』を参照してください。

- Oracle Glassfish Serverのインストールの詳細は、『Oracle GlassFish Serverインストレーション・ガイド』を参照してください。

3 WebLogic ServerでのTopLinkの使用

この章では、Oracle TopLinkをOracle WebLogic Serverにデプロイされたアプリケーションの永続性プロバイダとして使用する方法を説明します。

この章は次の項で構成されています。

- 3.1項「ソリューションの概要」

- 3.2項「ソリューションの実装」

- 3.3項「その他の参考資料」

ユース・ケース

WebLogic Serverの開発者、管理者およびユーザーが、TopLinkの永続性および変換サービスをすべて利用したいと考えています。

解決方法

WebLogic Serverでは他の永続性プロバイダを使用でき、TopLinkは他のアプリケーション・サーバーで使用できるので、WebLogic ServerをTopLinkとともに使用すると、多くの利点があります。

コンポーネント

- WebLogic Server 12c以上。WebLogic ServerにTopLinkが含まれます。

注意:

TopLinkのコア機能は、オープン・ソースのEclipse Foundationの永続性フレームワークであるEclipseLinkによって提供されています。EclipseLinkでは、Java Persistence API (JPA)、Java Architecture for XML Binding (JAXB)、および標準に基づいたその他の永続性テクノロジと、それらの標準の拡張が実装されます。TopLinkには、EclipseLinkのすべてに加え、Oracleの追加機能が含まれています。

- Oracle Database、Oracle Express、MySQLなど、対応するJava Database Connectivity (JDBC)データベース。

- 必須ではありませんが、Java EE統合開発環境(IDE)を開発に使用すると便利です。

サンプル

関連情報については、次のEclipseLinkの例を参照してください。

- http://wiki.eclipse.org/EclipseLink/Examples/JPA/WebLogic_Web_Tutorial

- http://wiki.eclipse.org/EclipseLink/Examples/JPA/WLS_AppScoped_DataSource

- http://wiki.eclipse.org/EclipseLink/Examples/Distributed

3.1 ソリューションの概要

WebLogic Serverは、エンタープライズ対応のスケーラブルなJava Platform, Enterprise Edition (Java EEプラットフォーム)アプリケーション・サーバーです。WebLogic ServerにはJava EE 6の仕様が完全に実装されており、データベースやメッセージング・サービス、外部のエンタープライズ・システムへの接続など広範なサービスにアクセス可能な分散Javaアプリケーションを作成するための標準APIセットが用意されています。WebLogic Serverでは、Java EEの実装に加えて、堅牢かつセキュアで可用性が高くスケーラブルな環境にクリティカルなアプリケーションを企業がデプロイできるようになっています。これらの特徴により、企業はWebLogic Serverインスタンスのクラスタを構成し、ロードを分散し、ハードウェアまたはその他の障害が発生した際にかわりとなる処理能力を提供できます。WebLogic Serverのこれらおよび他の機能の詳細は、WebLogic Serverの概要に関するマニュアルを参照してください。

TopLinkには、(Java SEアプリケーションに加え)Java EEアプリケーションの永続性レイヤーを実装するためのAPIとランタイム環境が備わっています。

3.1.1 WebLogic ServerでTopLinkを使用する利点

WebLogic Serverでは他の永続性プロバイダを使用でき、TopLinkは他のアプリケーション・サーバーで使用できるので、WebLogic ServerをTopLinkとともに使用すると、次のような多くの利点があります。

- EclipseLinkは、JPA 2.1をサポートするWebLogic Serverドメインのデフォルトの永続性プロバイダです。

- EclipseLinkに実装されているJava Architecture for XML Binding (JAXB)は、WebLogic ServerのデフォルトのJAXBの実装です。EclipseLinkはJAXBを完全に実装するのみではなく、その他の高度な機能も含んでいます。Java API for XML Web Services (JAX-WS)およびJava API for RESTful Web Services (JAX-RS)アプリケーションのEclipseLink JAXBの利点をデフォルトで利用できます。

- Oracle WebLogic Suiteには、データ・キャッシング、データ・レプリケーションおよび分散コンピューティング・サービスを提供するJavaベースのインメモリー・データグリッド製品であるOracle Coherenceが含まれています。WebLogic ServerとCoherenceは密に統合されているので、アプリケーションはCoherenceのデータ・キャッシュを使用できます。WebLogic ServerにデプロイされたEclipseLinkアプリケーションでは、Oracle TopLink Gridを使用して、Coherenceをエンティティのレベル2 (L2)キャッシュおよび永続性レイヤーとして使用してEclipseLink JPAと統合できます。詳細は、『Oracle Coherenceでのアプリケーションの開発』および『Oracle Coherenceの統合』を参照してください。

注意:

別途ライセンスされた製品としてCoherenceを入手して、WebLogic Server Standard EditionおよびWebLogic Server Enterprise Editionを使用することもできます。

- WebLogic ServerにEclipseLinkのロギングを統合することにより、包括的な統合ロギング・インフラストラクチャが実現されています。3.2.4項「タスク4: ロギング統合の使用または再構成」を参照してください。

- WebLogic Serverでは、StrutsおよびJavaServer Faces (JSF)に基づくエンドツーエンドのJava EEフレームワークであるOracle Application Development Framework (Oracle ADF)をサポートしています。Oracle ADFでは、インフラストラクチャ・サービスおよび視覚的で宣言的な開発エクスペリエンスを実現することにより、アプリケーション開発が簡素化されています。TopLinkおよびOracle ADFをともに使用することにより、完全なJava EEアプリケーション・インフラストラクチャが実現されます。Oracle ADFについては、このマニュアルでは説明しません。『Oracle Application Development FrameworkによるFusion Webアプリケーションの開発』を参照してください。

- WebLogic Server、TopLinkおよびOracle ADFはすべて、TopLinkを永続性プロバイダとして使用し、WebLogic Serverにデプロイされるアプリケーションを含むJava EEアプリケーションのモデリング、開発、デバッグ、最適化およびデプロイをサポートするOracleの統合開発環境(IDE)であるOracle JDeveloperと統合されています。JDeveloperの使用方法は、このドキュメントでは説明しません。JDeveloperに関する一般的な情報は、http://www.oracle.com/technetwork/developer-tools/jdev/overview/index.htmlを参照してください。JDeveloperのタスクに関する情報は、JDeveloper IDEのJDeveloperオンライン・ヘルプを参照してください。

3.1.2 TopLinkおよびその他のFusion Middleware製品

図3-1は、他のOracle製品に対するWebLogic ServerとTopLinkの関係および使用方法を示しています。次のように、製品をともに使用することが可能です。

- JDeveloper (またはOracle Enterprise Pack for EclipseまたはNetBeans)をJava EEアプリケーションの開発に使用します。

- 永続性プロバイダとしてEclipseLinkを使用します。

- データのキャッシュ、データのレプリケーション、分散コンピューティング・サービスに(TopLink Gridへの統合を介して)Oracle Coherenceを使用します。

- アプリケーション・サーバーとしてWebLogicを使用します。

- EclipseLink JPAアプリケーションからのデータを永続化するにはOracle Databaseを使用し、EclipseLink JAXBアプリケーションからデータを永続化するには、XMLを使用します。

図3-1 WebLogic Server、TopLinkおよび関連製品の関係

3.2 ソリューションの実装

EclipseLink JPAアプリケーションをWebLogic Serverで実行するには、次のタスクに示すとおり、WebLogic Serverを構成してサーバーとアプリケーションで特定の設定を調整する必要があります。

- タスク1: 前提条件

- オプションのタスク: WebLogic ServerでのEclipseLinkのリリースの更新(オプション)

- タスク3: WebLogic ServerのJMX MBean拡張の構成

- タスク4: ロギング統合の使用または再構成

- タスク5: EclipseLinkを使用したJavaアプリケーションへの永続性の追加

- タスク6: データ・ソースの構成

- タスク7: Oracleデータベースの高度な機能を使用するためのドメインの拡張

- タスク8: WebLogic Serverの起動とアプリケーションのデプロイ

- タスク9: アプリケーションの実行

- タスク10: WebLogic Serverの永続性設定の構成および監視

3.2.1 タスク1: 前提条件

このドキュメントは、次の製品およびツールに基づいていますが、原則は、サポートされているすべてのデータベースまたは開発環境に適用できます。後の項で特記されている場合以外、ソフトウェアはすでにインストールされているものと仮定しています。

- WebLogic Server 12c以上。
詳細およびダウンロードは、Oracle Technology Networkのhttp://www.oracle.com/technetwork/middleware/weblogic/overview/index.htmlを参照してください。

- Oracle Database、Oracle Express、MySQLなど、対応するすべてのJava Database Connectivity (JDBC)データベース。
Oracle Databaseについては、http://www.oracle.com/technetwork/database/enterprise-edition/overview/index.htmlを参照してください。Oracle Database Express Editionについては、http://www.oracle.com/technetwork/database/express-edition/overview/index.htmlを参照してください。MySQLについては、http://www.oracle.com/us/products/mysql/index.htmlを参照してください。

- 必須ではありませんが、Java開発環境(IDE)を開発に使用すると便利です。たとえば、JDeveloper、Oracle Enterprise Pack for EclipseおよびNetBeansにはすべて、高度なJava EE開発ツールが用意されています。このドキュメントでは、WebLogic Serverのスタンドアロン・インスタンスについて説明しますが、JDeveloperとOracle Enterprise Pack for Eclipseの両方にWebLogic Serverの組込みバージョンが含まれています。
JDeveloperについては、http://www.oracle.com/technetwork/developer-tools/jdev/downloads/index.htmlを参照してください。Oracle Enterprise Pack for Eclipseについては、http://www.oracle.com/technetwork/developer-tools/eclipse/overview/index.htmlを参照してください。NetBeansについては、http://www.oracle.com/us/products/tools/050845.htmlを参照してください。

3.2.2 オプションのタスク: WebLogic ServerでのEclipseLinkのリリースの更新(オプション)

古いバージョンのWebLogic Serverを使用している場合、使用されているEclipseLinkのバージョンを更新できます。より新しいTopLinkの配布からeclipselink.jarを取得し、次の手順で説明するとおり、WebLogic Serverのフィルタリング・クラス・ローダーおよび共有ライブラリ機能を使用します。

FilteringClassLoaderクラスは、デプロイメント・ディスクリプタを構成して、特定のパッケージが常にシステム・クラス・ローダーではなくアプリケーションからロードされるように指定するメカニズムがあります。このメカニズムを使用すれば、新しいリリースのEclipseLinkがアプリケーションで使用されるように指定できます。WebLogic Serverでのクラスローダーのフィルタリングの詳細は、『Oracle WebLogic Serverアプリケーションの開発』のフィルタリング・クラスローダーの使用方法に関する項を参照してください。

共有ライブラリは、複数のエンタープライズ・アプリケーションで共有できるJava EEモジュールです。共有ライブラリはWebLogic Serverのターゲットにデプロイされ、その後アプリケーションで参照できるようになります。デプロイされると、WebLogic Serverでは、共有ライブラリの内容がアプリケーションとマージされます。さらに、共有ライブラリは標準のJava EEアーカイブとしてパッケージ化できるので、デプロイ時には、ディスクリプタもアプリケーションとマージされます。WebLogic Serverの共有ライブラリの詳細は、『Oracle WebLogic Serverアプリケーションの開発』のJava EEの共有ライブラリおよびオプション・パッケージの作成に関する項を参照してください。

様々なリリースでサポートされている内容については、次を参照してください。

- http://www.oracle.com/technetwork/middleware/ias/jpa-082702.html#eclipselinkにあるOracle TopLink: JPA認証に関する項

- http://www.oracle.com/technetwork/middleware/ias/weblogic-086699.htmlにあるOracle TopLinkおよびWebLogicのサポートに関する項

WebLogic ServerでEclipseLinkのリリースを更新するには、次の手順を実行します。

1. http://www.oracle.com/technetwork/middleware/toplink/downloads/index.htmlから必要なTopLinkのバージョンをダウンロードし、eclipselink.jarファイルを探します。TopLinkのクイック・インストーラを使用して作成されたディレクトリでは、eclipselink.jarファイルは、oracle_common\modules\oracle.toplink_version_noにあります。クイック・インストーラの詳細は、第2章「Oracle TopLinkのインストール」を参照してください。

2. アプリケーションのlibディレクトリにeclipselink.jarファイルを配置します。

3. 次のアイテムを含む共有ライブラリを、eclipselink-shared-lib.earなどの名前を付けた標準Java EE Enterprise Archive (EAR)として準備します。

META-INF/weblogic-application.xml
META-INF/application.xml
lib/eclipselink.jar

EARの作成の詳細は、『Oracle WebLogic Server Webアプリケーション、サーブレット、JSPの開発』のWebアプリケーションの作成と構成に関する項を参照してください。

4. 次に示すとおり、サブ要素<package-name>org.eclipse.persistence.*</package-name>が指定されたprefer-application-packages要素をアプリケーションのweblogic-application.xmlディスクリプタ・ファイルに追加します。

<weblogic-application>
<prefer-application-packages>
<package-name>org.eclipse.persistence.*</package-name>
</prefer-application-packages>
</weblogic-application>

5. アプリケーションのapplication.xmlファイルを作成します。このファイルは、ランタイム・ライブラリのマージをサポートするために必要です。最小構成は次のとおりです。

<application>
<display-name>eclipselink-shared-lib</display-name>
<module>
<java></java>
</module>
</application>

6. 拡張の名前、仕様バージョンおよび実装バージョンをEARのMETA-INF/MANIFEST.MFファイルに追加します。たとえば、Apache Antを使用している場合は次を実行できます。

<target name="package" depends="prepare">
<jar destfile="dist/${ant.project.name}.ear">
<metainf dir="etc" includes="*.xml"/>
<manifest>
<attribute name="Extension-Name" value="eclipselink"/>
<attribute name="Specification-Version" value="2.0"/>
<attribute name="Implementation-Version" value="2.2.0"/>
</manifest>
<fileset dir="build" includes="**/*"/>
</jar>
</target>

デプロイ時には、デプロイされた共有ライブラリのメタデータとして、WebLogic Serverがこの属性を使用します。

最終的なEARファイル、次のようになります。

META-INF/
META-INF/MANIFEST.MF
META-INF/application.xml
META-INF/weblogic-application.xml
lib/
lib/eclipselink.jar

7. WebLogic Serverにeclipselink-shared-lib.earファイルをデプロイします。この結果、サーバーeclipselink#2.0@2.2.0で新しいライブラリが使用可能になります。

8. 次に示すとおり、更新されたリリースのEclipseLinkを使用するアプリケーションのweblogic-application.xmlファイルに、共有ライブラリへの参照を追加します。

<weblogic-application>
<library-ref>
<library-name>eclipselink</library-name>
<specification-version>2.0</specification-version>
<implementation-version>2.2.0</implementation-version>
</library-ref>
</weblogic-application>

3.2.3 タスク3: WebLogic ServerのJMX MBean拡張の構成

WebLogic ServerはJava Management Extensions (JMX) MBeanを使用して、WebLogic Serverのリソースを構成、監視および管理します。EclipseLinkのアプリケーションの場合、MBeanは永続性ユニットの様々な面の監視および設定に使用され、ロギングにも使用されます。

注意:

EclipseLinkのアプリケーションがWebLogic Serverにデプロイされている場合、デプロイ時ではなくデータベースへの接続時にMBeanがデプロイされます。

WebLogic ServerでMBeanがどのように使用されるかの詳細は、『Oracle WebLogic Server JMXによるカスタム管理ユーティリティの開発』および『Oracle WebLogic Server JMXによる管理可能アプリケーションの開発』を参照してください。

WebLogic ServerでのEclipseLinkのロギングの詳細は、3.2.4項「タスク4: ロギング統合の使用または再構成」を参照してください。

デフォルトでは、EclipseLinkアプリケーションをWebLogic Serverにデプロイすると、EclipseLinkのランタイムが、各EclipseLinkセッションのWebLogic Server JMXサービスに対して、次のJMX MBeanをデプロイします。

- org.eclipse.persistence.services.DevelopmentServices: これは、EclipseLinkの内部的なEclipseLinkセッションをJMX経由で管理する機能を提供するためのクラスです。

- org.eclipse.persistence.services.RuntimeServices: これは、EclipseLinkの外部的なEclipseLinkセッションをJMX経由で管理する機能を提供するためのクラスです。

このJMX MBeanが公開するAPIを使用すれば、自分で記述したJMXコードを使用してEclipseLinkセッションの実行時にアクセスおよび構成をしたり、JConsoleなどのサード・パーティのJMX管理アプリケーションを使用してEclipseLinkアプリケーションを統合したりできます。

カスタムMBeanに関するアクセス情報を入手するには、まず匿名参照を有効にしてから、別のツールを使用してMBean情報にアクセスします。

WebLogic Serverの管理コンソールで匿名参照を有効にするには、次の手順を実行します。

1. まだ行っていない場合は、管理コンソールのチェンジ・センターで「ロックして編集」をクリックします。

2. まず左側のペインで、ドメインを選択し、ドメインの「設定」ページを開きます。

3. 「セキュリティ」→「一般」を展開します。

4. 「匿名Adminのルックアップを有効化」を選択します。

5. これらの変更を有効にするために、管理コンソールの「チェンジ・センター」で「変更のアクティブ化」をクリックします。

様々なツールを使用してMBeanにアクセスする方法の詳細は、『Oracle WebLogic Server JMXによる管理可能アプリケーションの開発』のカスタムMBeanへのアクセスに関する項を参照してください。

管理コンソールでカスタムMBeanを監視する方法の詳細は、Oracle WebLogic Server管理コンソール・オンライン・ヘルプのカスタムMBeanの監視に関する項を参照してください。

3.2.4 タスク4: ロギング統合の使用または再構成

デフォルトでは、EclipseLinkのロギングはWebLogic Serverのロギング・インフラストラクチャに統合されます。統合の動作の詳細およびそれをオーバーライドする方法は、次の項を参照してください。WebLogic Serverのロギングの詳細は、次を参照してください。

- Oracle WebLogic ServerにデプロイされたアプリケーションへのWebLogicロギング・サービスの追加

- Oracle WebLogic Serverのログ・ファイルの構成とログ・メッセージのフィルタ処理

- Oracle WebLogic Serverの管理コンソール・オンライン・ヘルプのロギングに関する項

JPA永続性ユニットに対するロギングの構成方法の詳細は、http://wiki.eclipse.org/EclipseLink/Examples/JPA/LoggingにあるEclipseLinkドキュメントの『How to Configure Logging』を参照してください。

3.2.4.1 ロギング統合の動作方法

デフォルトでは、WebLogic Serverのロギング実装は永続性コンテキストに注入されるので、WebLogic Serverのロギング構成に従ってEclipseLinkのすべてのロギング・メッセージが生成されるようになります。

この統合の結果、表3-1に示すとおり、EclipseLinkのロギング・レベルがWebLogic Serverのロギング・レベルに変換されます。

表3-1 WebLogic Serverのロギング・レベルへのEclipseLinkのロギング・レベルのマッピング

EclipseLinkのロギング・レベル

WebLogic Serverのロギング・レベル

ALL、FINEST、FINER、FINE

DEBUG

CONFIG

INFO

INFO

NOTICE

WARNING

WARNING

SEVERE

ALERT

OFF

OFF

表3-2に示すとおり、WebLogic Serverのロギング・レベルがEclipseLinkのレベルにマップされます。

表3-2 EclipseLinkのロギング・レベルへのWebLogic Serverのロギング・レベルのマッピング

WebLogic Serverのロギング・レベル

EclipseLinkのロギング・レベル

TRACE、DEBUG

FINEST

INFO

CONFIG

NOTICE

INFO

WARNING

WARNING

ERROR、CRITICAL、ALERT

SEVERE

EMERGENCY、OFF

OFF

3.2.4.2 管理コンソールでの永続性ユニットのロギング・レベルの表示

3.2.10項「タスク10: WebLogic Serverの永続性設定の構成および監視」に説明されているように、永続性ユニットに定義されているEclipseLinkのロギング・レベルを管理コンソールに表示できます。ただし、デフォルトのWebLogic ServerとEclipseLinkロギング統合を使用すると、persistence.xmlに設定されているこのロギング・レベルがオーバーライドされることに注意してください。統合をオーバーライドする手順は、3.2.4.3項「デフォルト・ロギング統合のオーバーライド」を参照してください。

デフォルト統合を使用すると、永続性に対するEnterprise JavaBeans (EJB)ロギング・オプションがすべてマップされて、管理コンソールのEclipseLinkのロギング出力が制御されます。

3.2.4.3 デフォルト・ロギング統合のオーバーライド

EclipseLinkのロギング・レベルはpersistence.xmlファイルに設定します。ただし、WebLogic Severとのデフォルト・ロギング統合を受け入れると、これらの設定は無視され、WebLogic Serverに設定されているロギング構成が使用されます。EclipseLinkのロギング・レベルは、EclipseLinkのネイティブのロギング実装を使用する場合のみに使用されます。

eclipselink.logging.loggerプロパティ名を別の設定にすると、デフォルト・ロギング統合をオーバーライドできます。EclipseLinkのデフォルト・ロギングを有効にするには、たとえばeclipselink.logging.loggerプロパティを次のように設定します。

<property name="eclipselink.logging.logger" value="DefaultLogger"/>

たとえばjava.util.loggingパッケージなど、EclipseLinkメッセージ用に別のログの実装を使用することも可能です。

<property name="eclipselink.logging.logger" value="JavaLogger"/>

3.2.4.4 EclipseLinkのロギングを公開するためのWebLogic Serverの構成

EclipseLinkのネイティブのロギング実装を使用する場合は、登録されたログの宛先にWebLogic ServerがJava Virtual Machine (JVM)の出力をリダイレクトするように構成すれば、EclipseLinkのロギング・メッセージをWebLogic Serverドメインのログ・ファイルに引き続き表示できます。

リダイレクトの詳細および手順は、『Oracle WebLogic Serverログ・ファイルの構成とログ・メッセージのフィルタ処理』のJVM出力のリダイレクトに関する項を参照してください。管理コンソールでこのオプションを設定するには、Oracle WebLogic Server管理コンソール・オンライン・ヘルプのJVM出力のリダイレクトに関する項を参照してください。

3.2.4.5 その他の考慮事項

次なども考慮します。

- メッセージID 2005000は、EclipseLinkのすべてのログ・メッセージに対して使用されています。

- 実行時にアプリケーションのエンティティ・マネージャ・ファクトリがEclipseLinkのロギング・インフラストラクチャおよびEclipseLinkのロギング設定のみを使用する場合でも、(ロギング・レベルの設定によっては)WebLogic Serverの統合ロガーによって処理される一部のロギング・メッセージがWebLogic Serverのコンソールまたはサーバー・ログにデプロイ中に表示される場合があります。

- WebLogic ServerのインストールにバンドルされているEclipseLinkとは別のリリースを(フィルタリング・クラスローダーを使用して)使用する場合に、デフォルトの統合ロギングを使用しようとすると、クラスローディングの競合のためにエラーが発生する可能性があります。この問題を回避するには、統合されたWebLogic Serverロガー以外のものにeclipselink.logging.loggerプロパティを明示的に設定してください。

3.2.5 タスク5: EclipseLinkを使用したJavaアプリケーションへの永続性の追加

EclipseLink JPAを使用してアプリケーションに対する永続性を実現することは、この章で説明する他のすべてのタスクで仮定されている基本的なタスクですが、実際のJPAプログラミング技法の大部分はこのドキュメントでは説明しません。WebLogic Serverでは、この章で説明する詳細以外に、EclipseLinkアプリケーションに対する特別な要件はありません。

この章では、EclipseLink (ランタイムおよびAPI)をWebLogic Serverで使用する場合に固有の機能、設定およびタスクについて説明します。JPAを使用したJavaアプリケーションの開発、パッケージ化およびデプロイの詳細は、次を参照してください。

- http://wiki.eclipse.org/EclipseLinkにあるEclipseLinkプロパティのwiki

- http://wiki.eclipse.org/EclipseLink/Documentation_CenterにあるEclipseLink Documentation Center

- http://jcp.org/en/jsr/detail?id=317にあるJava Persistence APIバージョン2.0仕様

- http://download.oracle.com/javaee/6/tutorial/doc/bnbpy.htmlにあるJava EE 6チュートリアルの第V部「永続性」

- JPAを使用したJavaアプリケーションのプログラミングについて説明したサード・パーティの書籍

TopLinkの機能と概念の詳細は、第1章「概要」および『Oracle TopLinkの理解』を参照してください。

WebLogic Serverのプログラミングについては、WebLogic Serverのマニュアル・セット内の特に次などの任意のマニュアルを参照してください。

- Oracle WebLogic Server用のEnterprise JavaBeansの構築

- 『Oracle WebLogic Serverアプリケーションの開発』

- Oracle WebLogic Serverへのアプリケーションのデプロイ

- Oracle WebLogic ServerのJDBCアプリケーションの開発

3.2.6 タスク6: データ・ソースの構成

WebLogic Serverでデータベース接続を構成するには、JDBCデータ・ソースをWebLogic Serverドメインに追加します。各WebLogicデータ・ソースは、データベース接続のプールを保有しています。アプリケーションは、Java Naming and Directory Interface (JNDI) ツリー上またはローカルのアプリケーション・コンテキスト内でデータ・ソースを検索し、getConnection()メソッドを使用してデータベース接続を予約します。データ・ソースおよびその接続プールは、システムの効率的な稼働を維持するための接続管理プロセスを備えています。

WebLogic ServerでJDBCを使用する方法の詳細は、次を参照してください。

- WebLogic ServerでJDBCを使用する方法の完全なドキュメントは、『Oracle WebLogic Server JDBCデータ・ソースの管理』の次の項を特に参照してください。

- WebLogic JDBCリソースの構成

- JDBCデータ・ソースの構成

- WebLogic Server管理コンソールでJDBCデータ・ソースを操作する方法の詳細は、Oracle WebLogic Server管理コンソール・オンライン・ヘルプのJDBCの構成に関する項のトピックを参照してください。

3.2.6.1 JPAアプリケーションのデータ・ソースを構成する方法

WebLogic ServerにデプロイされたJPAアプリケーションのデータ・ソースは、次のような様々な方法で構成できます。

- グローバル・スコープのJTAデータ・ソースの構成

- アプリケーション・スコープのJTAデータ・ソースの構成

- 非JTAデータ・ソースの構成およびアプリケーションのトランザクション管理

3.2.6.2 グローバル・スコープのJTAデータ・ソースの構成

最も一般的なデータ・ソース構成は、グローバル・スコープのJNDIデータ・ソースで、トランザクション管理にJava Transaction API (JTA)を使用して、persistence.xmlファイルに指定します。構成は次の手順のとおり簡単で、複数のアプリケーションがデータ・ソースにアクセスできます。

- WebLogic Serverでのデータ・ソースの作成

- persistence.xmlファイルの構成

3.2.6.2.1 WebLogic Serverでのデータ・ソースの作成

グローバル・スコープのJNDIデータ・ソースをWebLogic Server管理コンソールで設定するには、次を実行します。

1. Oracle WebLogic Server管理コンソール・オンライン・ヘルプのJDBC汎用データ・ソースの作成に関する項の説明に従って、新しいデータ・ソースを作成します。

注意:

EclipseLinkは、名前による標準のJNDIデータ・ソース・ルックアップを使用してアクセスできるWebLogic Serverのデータ・ソースと互換性があります。これらの手順では、汎用データ・ソースのウィザードについて説明します。

2. 必要に応じて、「新しいJDBCデータ・ソースの作成」ウィザードに値を入力します。詳細は、Oracle WebLogic Server管理コンソール・オンライン・ヘルプのJDBCデータ・ソースの作成に関する項を参照してください。

重要:

JDBCデータ・ソースのプロパティ・ページの「JNDI名」に使用する値は、persistence.xmlファイルの<jta-data-source>要素に使用する値と同じである必要があります。

3. Oracle WebLogic Server JDBCデータ・ソースの管理の接続プール機能の構成に関する項に従って、接続プールを構成します。接続プールの構成は、アプリケーションからの同時リクエストをEclipseLinkが処理する能力に影響を及ぼす可能性があります。リソースおよびアプリケーションの応答性を最適化するために接続プールをチューニングするのと同じ方法で、プロパティをチューニングしてください。

3.2.6.2.2 persistence.xmlファイルの構成

次の例3-1に示すとおり、persistence.xmlファイルに、transaction-typeがJTAであることを指定して、データ・ソースの名前をjta-data-source要素(前にjdbc/が付く場合とそうでない場合があります)に指定します。

例3-1 JTAを使用するJNDIデータ・ソースが指定されたpersistence.xmlファイル

...
<persistence-unit name="example" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>JDBC Data Source-1</jta-data-source>
<class>org.eclipse.persistence.example.jpa.server.business.Cell</class>
<class>org.eclipse.persistence.example.jpa.server.business.CellAttribute</class>
</persistence-unit>

3.2.6.3 アプリケーション・スコープのJTAデータ・ソースの構成

トランザクション管理にJTAを使用するアプリケーション・スコープのデータ・ソースを構成するには、次の手順を実行します。

1. データ・ソースがアプリケーション・スコープであることの指定

2. WebLogic Serverのアプリケーション構成へのJDBCモジュールの追加

3. JTAデータ・ソースを使用するためのJPA永続性ユニットの構成

3.2.6.3.1 データ・ソースがアプリケーション・スコープであることの指定

アプリケーション・スコープのデータ・ソースを定義するには、name-jdbc.xml JDBCモジュール・ファイルを作成して、アプリケーションのEARファイルのMETA-INFフォルダに置きます。例3-2に示すとおり、そのファイルのjdbc-data-source-paramsセクションに<scope>Application</scope>を追加します。

例3-2 name-jdbc.xmlファイルに定義されたJDBCデータ・ソース

<jdbc-data-source ...>
...
<jdbc-data-source-params>
<jndi-name>SimpleAppScopedDS</jndi-name>
<scope>Application</scope>
</jdbc-data-source-params>
</jdbc-data-source>

ヒント:

3.2.6.2項「グローバル・スコープのJTAデータ・ソースの作成」の説明に従って、WebLogic Server管理コンソールからグローバル・スコープのデータ・ソースを作成すれば、name-jdbc.xmlファイルのフレームワークを作成できますが、次の点が異なります。

- データ・ソースをサーバーに関連付けないでください

- <scope>要素を手動で追加してください

JDBCモジュール構成ファイルおよびjdbc-data-source (<jdbc-driver-paramsおよび<jdbc-connection-pool-paramsを含む)の詳細は、『Oracle WebLogic Server JDBCデータ・ソースの管理』のWebLogic JDBCリソースの構成に関する項を参照してください。

3.2.6.3.2 WebLogic Serverのアプリケーション構成へのJDBCモジュールの追加

例3-3に示すとおり、EARファイルの/META-INF/weblogic-application.xmlアプリケーション・デプロイメント・ディスクリプタにJDBCモジュールへの参照を追加します。これにより、アプリケーションで使用するデータ・ソースが登録されます。

例3-3 weblogic-application.xmlファイルに定義されたJDBCモジュール

<wls:module>
<wls:name>SimpleAppScopedDS</wls:name>
<wls:type>JDBC</wls:type>
<wls:path>META-INF/simple-jdbc.xml</wls:path>
</wls:module>

weblogic-application.xmlアプリケーション・デプロイメント・ディスクリプタの詳細は、『Oracle WebLogic Serverへのアプリケーションのデプロイ』のアプリケーション・デプロイメント・ディスクリプタの理解に関する項および『Oracle WebLogic Serverアプリケーションの開発』のエンタープライズ・アプリケーション・デプロイメント・ディスクリプタの要素に関する項を参照してください。

3.2.6.3.3 JTAデータ・ソースを使用するためのJPA永続性ユニットの構成

EclipseLinkランタイムがアプリケーション・スコープのデータ・ソースを遅延参照できるようにするには、persistence.xmlファイルの永続性ユニットの定義に追加のデータ・ソース・プロパティを指定する必要があります。例3-4に示すとおり、JTAデータ・ソースの場合は、javax.persistence.jtaDataSource完全修飾プロパティに値java:/app/jdbc/data_source_nameを指定して追加します。

<jta-data-source>プロパティの値と<javax.persistence.jtaDataSource>プロパティの値は一致する必要があります。

例3-4 persistence.xmlファイル内のJTAデータ・ソースの定義

<?xml version="1.0" encoding="windows-1252" ?>
<persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0" xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="employee" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>java:/app/jdbc/SimpleAppScopedDS</jta-data-source>
<properties>
<property name="javax.persistence.jtaDataSource"
value="java:/app/jdbc/SimpleAppScopedDS" />
</properties>
</persistence-unit>
</persistence>

3.2.6.4 非JTAデータ・ソースの構成およびアプリケーションのトランザクション管理

アプリケーションが管理する非JTAデータ・ソースを構成するには、3.2.6.3項「アプリケーション・スコープのJTAデータ・ソースの構成」の説明と同じことをしますが、例3-5に示すとおり、非JTAデータ・ソースを指定して、非JTAデータ・ソースを使用するようにJPAの永続性を構成します。

例3-5 persistence.xmlファイル内の非JTAデータ・ソースの定義

<?xml version="1.0" encoding="windows-1252" ?>
<persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0" xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="employee" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<non-jta-data-source>OracleDS</non-jta-data-source>
<properties>
<property name="javax.persistence.nonJtaDataSource"
value="OracleDS" />
</properties>
</persistence-unit>
</persistence>

たとえば、Oracle WebLogic Server JTAアプリケーションの開発のEJBアプリケーションのトランザクションに関する項に従って、トランザクションを処理するコードをアプリケーションに記述します。

3.2.6.5 設定の一致の確認

データ・ソース構成の特定の設定は、アプリケーションのejbModule/META-INF/persistence.xmlファイルの特定の設定と一致する必要があります。WebLogic Serverのデータ・ソース構成については、構成ファイルまたは管理コンソールで設定を確認できます。

管理コンソールでは、次のように設定を確認します。

1. 「ドメイン構造」ツリーで「サービス」を開き、「データ・ソース」を選択します。

2. 「JDBCデータ・ソースのサマリー」ページで、データ・ソースの名前をクリックします。

3. 「data_source_nameの設定」→「構成」→「一般」ページで、localDSなどの「JNDI名」の値を検索します。JTAを使用している場合は、persistence.xmlファイルの<jta-data-source>と名前が一致する必要があります。

4. 「data_source_nameの設定」→「構成」→「接続プール」ページで、これらの設定を確認します。

- 「URL」の値は、persistence.xmlファイルのjavax.persistence.jdbc.urlの値、たとえばjdbc:oracle:thin:@127.0.0.1:1521:XEと一致する必要があります。

- 「ドライバ・クラス名」の値は、persistence.xmlファイルのjavax.persistence.jdbc.driverの値、たとえば(JTAデータ・ソースの場合は)oracle.jdbc.xa.client.OracleXADataSourceと一致する必要があります。

例3-6では、ドメインのconfig.xmlファイルとアプリケーションのpersistence.xmlファイルで共有する必要がある値を示しています。

例3-6 サーバー・ドメインのconfig.xmlファイル

...
<domain...>
<jdbc-system-resource>
<name>localJTA</name>
<target>AdminServer,ManagedServer_1,ManagedServer_2</target>
<descriptor-file-name>jdbc/localJTA-4636-jdbc.xml</descriptor-file-name>
</jdbc-system-resource>
</domain>

3.2.7 タスク7: Oracle Databaseの高度な機能を使用するためのドメインの拡張

Oracle SpatialおよびOracle XDBマッピングの機能を(スタンドアロンのWebLogic ServerとJDeveloperに統合されたWebLogic Serverの両方で)完全にサポートするには、それぞれtoplink-spatial-template.jarファイルおよびtoplink-xdb-template.jarファイルを使用してWebLogic Serverドメインを拡張し、Oracle SpatialとOracle XDBをサポートする必要があります。

WebLogic Serverドメインを拡張するには、次の手順を実行します。

1. toplink-spatial-template.jarファイル(Oracle Spatialのサポート用)とtoplink-xdb-template.jarファイル(Oracle XDBのサポート用)を次の場所からダウンロードします。

- http://download.oracle.com/otn/java/toplink/111110/toplink-spatial-template.jar

- http://download.oracle.com/otn/java/toplink/111110/toplink-xdb-template.jar

2. 表3-3および表3-4に示されているファイルをコピーします。

表3-3 Oracle Spatialをサポートするためのファイル

ファイル

コピー元

目的

sdoapi.jar

ORACLE_DATABASE_HOME/md/jlib

WL_HOME/server/lib

表3-4 Oracle XDBをサポートするためのファイル

ファイル

コピー元

目的

xdb.jar

ORACLE_DATABASE_HOME/rdbms/jlib

WL_HOME/server/lib

xml.jar

ORACLE_DATABASE_HOME/lib

WL_HOME/server/lib

xmlparserv2.jar

ORACLE_DATABASE_HOME/lib

WL_HOME/server/lib

3. 構成ウィザード(WL_HOME/common/bin/config.sh (または.bat))を起動します。

4. 「既存のWebLogicドメインの拡張」を選択します。

5. WebLogic Serverドメインを参照して選択します。

6. 「既存の拡張テンプレートを使用してドメインを拡張する」を選択します。

7. 必要なテンプレートJARファイルを参照して選択します(Oracle Spatialの場合はtoplink-spatial-template.jar、Oracle XDBの場合はtoplink-xdb-template.jar)。

8. ウィザードの残りのページを完了します。

WebLogic Serverドメイン・テンプレートの使用方法の詳細は、ドメイン・テンプレート・リファレンスを参照してください。

3.2.8 タスク8: WebLogic Serverの起動とアプリケーションのデプロイ

WebLogic Serverヘのデプロイに関する詳細は、『Oracle WebLogic Serverへのアプリケーションのデプロイ』を参照してください。『Oracle Application Development FrameworkによるFusion Webアプリケーションの開発』のFusion Webアプリケーションのデプロイに関する項を参照してください。

3.2.9 タスク9: アプリケーションの実行

デプロイされたアプリケーションをWebLogic Server管理コンソールから起動する手順の詳細は、Oracle WebLogic Server管理コンソール・オンライン・ヘルプのデプロイされたエンタープライズ・アプリケーションの起動と停止に関する項を参照してください。

3.2.10 タスク10: WebLogic Serverの永続性設定の構成および監視

WebLogic Server管理コンソールでは、永続性ユニットを構成して、永続性ユニットのJTAおよび非JTAのデータ・ソースを次のように構成できます。

1. まだ行っていない場合は、管理コンソールのチェンジ・センターで「ロックして編集」をクリックします。

2. 管理コンソールの左ペインで、「デプロイメント」を選択します。

3. 右ペインで、構成するアプリケーションまたはモジュールを選択します。

4. 「構成」を選択します。

5. 「永続性」を選択します。

6. 構成する永続性ユニットを表から選択します。

7. 構成ページのプロパティを確認および編集します。ページのヘルプは、管理コンソールの上部の「ヘルプ」リンクをクリックすれば表示されます。
次のようなプロパティを表示できます。

- 名前

- プロバイダ

- 説明

- トランザクション・タイプ

- データ・キャッシュ・タイムアウト

- バッチ・サイズのフェッチ

- デフォルト・スキーマ名

- persistence.xmlファイルに定義されている永続性ユニット・プロパティの値、たとえば、eclipselink.session-name、eclipselink.logging.levelおよびeclipselink.target-server

永続性ユニットのトランザクション・データ・ソースと非トランザクション・データ・ソースに関連する属性も「データ・ソース」構成ページに設定できます。

8. これらの変更を有効にするために、管理コンソールの「チェンジ・センター」で「変更のアクティブ化」をクリックします。

管理コンソールの永続性の操作に関する他のヘルプ・トピックへのリンクについては、Oracle WebLogic Server管理コンソール・オンライン・ヘルプの目次で「永続性」を検索してください。

3.3 その他の参考資料

この章のソリューションが実装されているその他のテクノロジおよびツールの詳細は、次の参考資料を参照してください。

- Oracle WebLogic Serverのマニュアル

- 次などのOracle TopLink Java APIリファレンス

- org.eclipse.persistence

- org.eclipse.persistence.jpa.PersistenceProvider

- org.eclipse.persistence.services.mbean

4 GlassFish ServerでのTopLinkの使用

この章では、Oracle TopLinkをOracle GlassFish Serverにデプロイされたアプリケーションの永続性プロバイダとして使用する方法を説明します。

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

- 4.1項「ソリューションの概要」

- 4.2項「ソリューションの実装」

- 4.3項「その他の参考資料」

ユース・ケース

Oracle GlassFish ServerでJPAを使用するアプリケーションを実行したいとユーザーが考えています。

解決方法

Oracle GlassFishでは、EclipseLinkを完全にサポートしています。開発者がGlassFish Serverプラットフォーム用のアプリケーションを記述する場合、Java Persistence API (JPA) 2.0仕様に準拠させ、Javaとデータ・ソースを完全に統合できます。EclipseLinkでは、理想的なアプリケーション設計またはデータの整合性を損わずに、Javaアプリケーションをすべてのデータ・ソースと統合できます。

コンポーネント

- GlassFish Server 3.1.2.

- TopLink 12cリリース1 (12.1.2)以上。

注意:

TopLinkのコア機能は、オープン・ソースのEclipse Foundationの永続性フレームワークであるEclipseLinkによって提供されています。EclipseLinkでは、Java Persistence API (JPA)、Java Architecture for XML Binding (JAXB)、および標準に基づいたその他の永続性テクノロジと、それらの標準の拡張が実装されます。TopLinkには、EclipseLinkのすべてに加え、Oracleの追加機能が含まれています。

- Oracle Database、Oracle Database Express Edition、MySQLなどのJDBC準拠のすべてのデータベース。

- 必須ではありませんが、Java EE統合開発環境(IDE)を開発に使用すると便利です。

4.1 ソリューションの概要

Oracle GlassFish Serverは、Java Platform, Enterprise Edition (Java EEプラットフォーム)仕様のリファレンス実装です。GlassFish Server Open Source Editionを使用してビルドされたGlassFish Serverは、本番にすぐ使用できる柔軟で軽量なJava EEプラットフォームを提供します。

GlassFish Serverは製品のOracle Fusion Middlewareアプリケーション・グリッド・ポートフォリオの一部であり、エンタープライズJava EEプラットフォームの最新実装を使用した軽量インフラストラクチャを必要とするアプリケーションに最適です。GlassFish Serverは、Oracle Fusion Middlewareのより広範なポートフォリオおよび大規模なエンタープライズ・アプリケーションを実行するように設計されたOracle WebLogic Serverを補完する製品です。

4.1.1 GlassFish ServerでTopLinkを使用する利点

TopLinkサポートを追加することにより、GlassFish Serverプラットフォームのアプリケーション開発者が、Java Persistence API (JPA) 2.0仕様に準拠してJavaとデータ・ソースを完全に統合できるようになります。TopLinkでは、理想的なアプリケーション設計またはデータの整合性を損わずに、Javaアプリケーションをすべてのデータ・ソースと統合できます。また、TopLinkを使用すれば、GlassFish Serverプラットフォームのアプリケーションで、リレーショナル・データベースまたはXMLデータ・ソースをリポジトリとして使用して、ビジネス・ドメイン・オブジェクトをストア(永続化)および取得できるようになります。

GlassFish Serverでは他の永続性プロバイダを使用でき、TopLinkは他のアプリケーション・サーバーで使用できるので、GlassFish ServerをTopLinkとともに使用すると、次のような多くの利点があります。

- TopLinkはすべてのGlassFish Serverディストリビューションに含まれており、デフォルトのJPAプロバイダになります。

- TopLinkでは、GlassFish Serverで動作するアプリケーションでOracle Coherenceのキャッシュを使用できます。Coherenceは、データ・キャッシング、データ・レプリケーションおよび分散コンピューティング・サービスを提供するJavaベースのインメモリー・アプリケーション・グリッド製品です。TopLinkには、デプロイされたアプリケーションでCoherenceデータ・キャッシュを使用し、オブジェクトからリレーショナルへの永続化フレームワークとしてTopLink Gridを組み込む機能が含まれています。この機能の使用方法については、このガイドでは説明しません。詳細は、『Oracle Coherenceの統合』を参照してください。

- GlassFish ServerのTopLinkロギング統合では、包括的な統合ロギング・インフラストラクチャが実現されています。

- EclipseLink JAXBは、GlassFishバージョン3.1.2以上にも含まれています。デフォルトのJAXBの実装ではありませんが、JAX-WSおよびJAX-RSアプリケーションで使用できます。詳細は、http://blog.bdoughan.com/2012/02/glassfish-312-is-full-of-moxy.htmlを参照してください。

- GlassFish Serverでは、StrutsおよびJavaServer Faces (JSF)に基づくエンドツーエンドのJava EEフレームワークであるOracle Application Development Framework (Oracle ADF)をサポートしています。Oracle ADFでは、インフラストラクチャ・サービスおよび視覚的で宣言的な開発エクスペリエンスを実現することにより、アプリケーション開発が簡素化されています。TopLinkおよびOracle ADFをともに使用することにより、完全なJava EEアプリケーション・インフラストラクチャが実現されます。Oracle ADFについては、このマニュアルでは説明しません。『Oracle Fusion Middleware Oracle Application Development Framework Fusion開発者ガイド』を参照してください。

4.1.2 Fusion Middleware製品に対するGlassFish ServerとTopLinkの関係

図4-1は、他のOracle製品に対するGlassFish ServerとTopLinkの関係および使用方法を示しています。次にGlassFish ServerおよびTopLinkをその他のOracle Middleware製品とともに使用する方法を説明します。

- 永続性プロバイダとしてEclipseLinkを使用します。

- データのキャッシュ、データのレプリケーション、分散コンピューティング・サービスには(Oracle TopLink Gridの統合を介して)Oracle Coherenceを使用します。

- アプリケーション・サーバーとしてGlassFishを使用します。

- 永続性データとしてOracle Databaseを使用します。

注意:

Oracle CoherenceおよびTopLink Gridについては、このガイドでは説明しません。Coherenceの詳細は、『Oracle Coherenceでのアプリケーションの開発者』およびCoherenceのその他のドキュメントへのリンクを参照してください。TopLink Gridの詳細は、「Oracle Coherenceの統合」を参照してください。

図4-1 Oracle Fusion MiddlewareスタックのGlassFish Server、TopLinkおよびその他の製品

4.2 ソリューションの実装

EclipseLink JPAアプリケーションをGlassFish Serverで実行するには、サーバーを構成して、サーバーとアプリケーションの特定の設定を調整する必要があります。これらについては、次のタスクで説明します。

- タスク1: 前提条件

- タスク2: GlassFish Serverのインストール

- タスク3: データ・ソースの設定

- タスク4: persistence.xmlファイルの作成

- タスク5: JPA用のGlassFish Serverの設定

- タスク6: アプリケーションの作成

- タスク7: GlassFish Serverに対するアプリケーションのデプロイ

- タスク8: アプリケーションの実行

- タスク9: アプリケーションの監視

4.2.1 タスク1: 前提条件

このドキュメントは、次の製品およびツールに基づいていますが、原則は、サポートされているすべてのデータベースまたは開発環境に適用できます。後の項で特記されている場合以外、ソフトウェアはすでにインストールされているものと仮定しています。

- GlassFish Server 3.1.2.
詳細およびダウンロードは、Oracle Technology Networkのhttp://www.oracle.com/technetwork/middleware/glassfish/overview/index.htmlを参照してください。

- EclipseLink 2.4.1。
詳細およびダウンロードについては、EclipseLink Webサイトのhttp://www.eclipse.org/eclipselink/を参照してください。

- Oracle Database、Oracle Database Express Edition、MySQLなどのJDBC準拠のすべてのデータベース。
Oracle Databaseについては、http://www.oracle.com/technetwork/database/enterprise-edition/overview/index.htmlを参照してください。

Oracle Database Express Editionについては、http://www.oracle.com/technetwork/database/express-edition/overview/index.htmlを参照してください。

MySQLについては、http://www.oracle.com/us/products/mysql/index.htmlを参照してください。

- 必須ではありませんが、Java EE統合開発環境(IDE)を開発に使用すると便利です。たとえば、Oracle JDeveloper、Oracle Enterprise Pack for EclipseおよびNetBeansにはすべて、高度なJava EE開発ツールが用意されています。
JDeveloperについては、http://www.oracle.com/technetwork/developer-tools/jdev/downloads/index.htmlを参照してください。

Oracle Enterprise Pack for Eclipseについては、http://www.oracle.com/technetwork/developer-tools/eclipse/overview/index.htmlを参照してください。

NetBeansについては、http://www.oracle.com/us/products/tools/050845.htmlを参照してください。

4.2.2 タスク2: GlassFish Serverのインストール

EclipseLinkは、GlassFish Serverの配布に含まれています。インストールおよび構成の手順の詳細は、Oracle GlassFish Serverのドキュメント・ライブラリを参照してください。

EclipseLinkのモジュールは、modulesディレクトリに個別のJARファイルとして表示されます。

* \glassfish\modules
.
.
.
o org.eclipse.persistence.antlr.jar
o org.eclipse.persistence.asm.jar
o org.eclipse.persistence.core.jar
o org.eclipse.persistence.jpa.jar
o org.eclipse.persistence.jpa.modelgen.jar
o org.eclipse.persistence.moxy.jar
o org.eclipse.persistence.oracle.jar
.
.
.

注意:

- Coherenceのキャッシュをサポートするtoplink-grid.jarファイルを使用できるのは、Oracle Coherenceのライセンスを購入した場合のみです。toplink-grid.jarファイルで提供される機能の詳細は、「Oracle Coherenceの統合」を参照してください。

- org.eclipse.persistence.oracle.jarファイルはGlassFishで使用可能で、EclipseLinkに対するOracle Database固有の機能を提供します。このファイルは、Oracle Databaseに対して実行されるアプリケーションのみに対して使用されます。

Object-XML (JAXBサポート)は、XMLスキーマにJavaクラスをバインドできるようにするコンポーネントです。このサポートは、org.eclipse.persistence.moxy.jarによって提供されています。

4.2.3 タスク3: データ・ソースの設定

Java EEアプリケーションのJDBCリソースとしてOracle Databaseを構成するには、次の手順を実行します。

1. GlassFish ServerへのOracleデータベースのJDBCドライバの統合

2. リソースに対するJDBC接続プールの作成

3. JDBCリソースの作成

4.2.3.1 GlassFish ServerへのOracleデータベースのJDBCドライバの統合

JDBCドライバを統合するには、JARファイルをドメインにコピーしてから、ドメインおよびインスタンスを再起動し、ドライバを使用可能にします。

1. JDBCドライバのJARファイルをドメインのlibサブディレクトリに、次のようにコピーします。

cd /home/gfuser/glassfish3
cp oracle-jdbc-drivers/ojdbc6.jar glassfish/domains/domain1/lib

ドライバは動的にピックアップされるので、GlassFish Serverを再起動する必要はありません。

EclipseLinkで提供されるOracle Database固有の拡張機能をアプリケーションが使用している場合は、ドライバをlib/extディレクトリにコピーする必要があります。詳細は、『Oracle GlassFish Serverアプリケーション開発ガイド』のOracle Databaseの拡張機能に関する項を参照してください。

2. GlassFish Serverの管理コンソールまたはコマンドラインを使用して、ドメインのインスタンスを再起動し、インスタンスでJDBCドライバを使用できるようにします。
GlassFish Server管理コンソールを使用するには:

GlassFish Serverの管理コンソールで「クラスタ」ノードを展開します。クラスタのノード選択して、「一般情報」ページで、「インスタンス」タブをクリックします。再起動するインスタンスを選択します。詳細は、GlassFish Server管理コンソール・オンライン・ヘルプのクラスタ化されたGlassFish Serverインスタンスの起動に関する項を参照してください。

スタンドアロン・インスタンスを起動するには、「スタンドアロン・インスタンス」ノードを展開します。起動する各インスタンスを、「サーバー・インスタンス」表から選択します。「起動」をクリックします。インスタンスが起動すると、「サーバー・インスタンス」の表の各インスタンスのステータスが更新されます。詳細は、GlassFish Server管理コンソール・オンライン・ヘルプのスタンドアロンのGlassFish Serverインスタンスの起動に関する項を参照してください。

コマンドラインを使用するには:

restart-instanceサブコマンドを実行して、インスタンスを再起動します。これらのコマンドでは、インスタンスの名前がpmd-i1およびpmd-i2である仮定しています。

restart-instance pmd-i1
restart-instance pmd-i2

4.2.3.2 リソースに対するJDBC接続プールの作成

JDBC接続プールは、GlassFish Server管理コンソールまたはコマンドラインから作成できます。

GlassFish Server管理コンソールを使用するには:

GlassFish Server管理コンソールで、「共通タスク」ノードを展開して、「共通タスク」ページの「新規JDBC接続プールの作成」ボタンをクリックします。プールの名前、リソース・タイプ、データベース・プロバイダの名前、データ・ソースとドライバ・クラスの名前、および他の詳細を指定します。詳細は、GlassFish管理コンソール・オンライン・ヘルプのJDBC接続プールの作成に関する項を参照してください。

コマンドラインを使用するには:

1. create-jdbc-connection-poolサブコマンドを使用して、JDBC接続プールを作成し、データベース接続の値を指定します。このコマンドでは、URLプロパティ値の前に2つのバック・スラッシュ(\\)を使用していることに注意してください。これらのバック・スラッシュにより、コロンがプロパティと値のペアのセパレータとしてではなく、プロパティ値の一部として解釈されるようになります。次に例を示します。

create-jdbc-connection-pool
--datasourceclassname oracle.jdbc.pool.OracleDataSource
--restype javax.sql.DataSource
--property User=smith\\:Password=password\\:url=jdbc\\:oracle\\:thin\\:@node_name.example.com\\:1521\\:smithdb
poolbvcallbackbmt

2. データベースへの接続を確認します。

ping-connection-pool pool_name

4.2.3.3 JDBCリソースの作成

GlassFish Server管理コンソールを使用してJDBCリソースを作成することも、コマンドラインを使用することもできます。

GlassFish Server管理コンソールを使用するには:

GlassFish Server管理コンソールで、「リソース」ノード→「JDBC」ノード→「JDBCリソース」ノードの順に展開して、「JDBCリソース」ページをオープンします。一意のJNDIリソース名を指定して、リソースを接続プールと関連付けます。詳細は、GlassFish Server管理コンソール・オンライン・ヘルプのJDBCリソースの作成に関する項を参照してください。

コマンドラインを使用するには:

create-jdbc-resourceサブコマンドを使用して、JDBCリソースを作成し、次のように、JNDIルックアップによってアプリケーションがJDBCリソースを見つけられるような名前を付けます。

create-jdbc-resource --connectionpoolid poolbvcallbackbmt jdbc/bvcallbackbmt

4.2.4 タスク4: persistence.xmlファイルの作成

例4-1に、EclipseLinkのデフォルト永続性プロバイダorg.eclipse.persistence.jpa.PersistenceProviderを指定するpersistence.xmlのサンプル・ファイルを示します。このファイルの詳細は、『Oracle TopLinkの理解』の永続性ユニットに関する項を参照してください。

デフォルトの永続性プロバイダを使用している場合は、『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』のその他のデータベース・プロパティを指定できます。

ファイルに入力する値のいくつかは、次に示すとおり、クラスタ、接続および接続プールのプロパティをGlassFish Serverに定義したときに選択した値と一致する必要があります。

JDBCデータ・ソースのプロパティ:

- 名前: 通常はJNDI名と同じ、jdbc/bvcallbackbmtなどのデータ・ソースの名前。

- JNDI名: このデータ・ソースがバインドされる場所へのJNDIパス。これは、persistence.xmlの<jta-data-source>要素の値と同じにする必要があります。たとえば、jdbc/bvcallbackbmtのように指定します。

- データベース・タイプ: Oracle

- データベース・ドライバ: (デフォルト) インスタンス接続用のOracleのドライバ(Thin XA)。バージョン: 9.0.1以降

接続プロパティ:

- データベース名: Oracle Database Express Editionのサンプルの場合はXEなどのデータベースの名前。

- ホスト名: データベース・サーバーのIPアドレス。たとえば、ローカルにホストされているデータベースの場合は127.0.0.1です。

- ポート: Oracle Database Express Edition 11gのデフォルトである1521など、データベース・サーバーが接続要求をリスニングするポート番号。

- データベース・ユーザー名: Oracle Database Express 11gのサンプルの場合はhrなどの、データベース接続を作成するために使用するデータベース・アカウントのユーザー名。

- パスワード: 使用するパスワード。

ターゲットの選択:

- サーバー/クラスタ: データ・ソースをデプロイする管理サーバー、管理対象サーバーまたはクラスタを選択。1つ以上を選択できます。

例4-1のpersistence.xmlのサンプル・ファイルでは、永続性プロバイダ、JTAデータ・ソースおよびロギングの詳細を定義するプロパティを示しています。この例では、ロギング・レベルはFINEに設定されています。このレベルでは、EclipseLinkによって生成されるSQLコードはserver.logファイルにロギングされます。これらのプロパティの詳細は、次を参照してください。

- 4.2.4.1項「永続性プロバイダの指定」

- 4.2.4.2項「Oracle Databaseの指定」

- 4.2.4.3項「ロギングの指定」

例4-1 persistence.xmlのサンプル・ファイル

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<persistence-unit name="pu1" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/bvcallbackbmt</jta-data-source>
<properties>
<property name="eclipselink.logging.level" value="FINE"/>
<property name="eclipselink.ddl-generation"
value="drop-and-create-tables"/>
</properties>
</persistence-unit>
</persistence>

4.2.4.1 永続性プロバイダの指定

永続性プロバイダでは、JPAの実装を定義します。これは、persistence.xmlファイルのprovider要素に定義されています。永続性プロバイダはベンダー固有のものです。EclipseLinkの永続性プロバイダはorg.eclipse.persistence.jpa.PersistenceProviderです。

4.2.4.2 Oracleデータベースの指定

データベース接続の詳細はpersistence.xmlファイルに指定します。GlassFish Serverのデフォルトでは、バンドルされている、jdbc/__defaultという名前のJava DB (Derby)データベースが使用されます。Oracle Databaseなどのデフォルト以外のデータベースを使用するには、jta-data-source要素に値を指定するか、transaction-type要素にRESOURCE_LOCALを設定して、non-jta-data-source要素に値を指定します。

デフォルトの永続性プロバイダorg.eclipse.persistence.jpa.PersistenceProviderを使用している場合は、接続メタデータに基づいて、プロバイダがデータベース・タイプの自動検出を試みます。このデータベース・タイプを使用して、検出されたデータベース・タイプに固有のSQL文が発行されます。オプションのeclipselink.target-databaseプロパティを指定すれば、データベース・タイプが正しいことを保証できます。

GlassFish Server用にpersistence.xmlファイルでデータベース・プロパティを指定する方法の詳細は、『Oracle GlassFish Serverアプリケーション開発ガイド』のアプリケーション用のデータベースの指定に関する項を参照してください。

4.2.4.3 ロギングの指定

ロギングはJPA仕様の一部ではありませんが、EclipseLinkにはロギング・ユーティリティが用意されています。そのため、ログで提供される情報はEclipseLink JPA固有のものです。EclipseLinkでロギングを有効にすれば、次の情報を確認できます。

- 構成の詳細

- デバッグを容易にするための情報

- データベースに送信されるSQL

ロギングはpersistence.xmlファイルに指定できます。EclipseLinkのロギング・プロパティでは、ロギングのレベル、およびログの出力をファイルまたは標準出力のどちらにするかを指定できます。ロギング・ユーティリティはjava.util.loggingに基づいているので、使用するロギング・レベルを指定できます。

ロギング・ユーティリティには、ログ出力の量および詳細度を制御するロギング・レベルが9種類用意されています。ロギング・レベルは、次のようにeclipselink.logging.levelを使用して設定します。

<property name="eclipselink.logging.level" value="FINE"/>

デフォルトでは、System.outまたはコンソールにログが出力されます。出力がファイルにロギングされるように構成するには、eclipselink.logging.fileプロパティを次のように設定します。

<property name="eclipselink.logging.file" value="output.log"/>

EclipseLinkのロギング・ユーティリティはプラガブルで、java.util.loggingなどの数種類のロギング統合がサポートされています。java.util.loggingを有効にするには、eclipselink.logging.loggerプロパティを次のように設定します。

<property name="eclipselink.logging.logger" value="JavaLogger"/>

GlassFish Server内でEclipseLinkを実行している間は、デフォルトでJavaLoggerを使用するようにGlassFish Serverによって構成されます。ログは常にGlassFish Serverのserver.logファイルにリダイレクトされます。詳細は、『Oracle GlassFish Server管理ガイド』のログ・レベルの設定に関する項を参照してください。

EclipseLinkでのロギングおよびロギング・ユーティリティで利用可能なロギング・レベルの詳細は、『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』の永続性プロパティの拡張のリファレンスに関する項を参照してください。

4.2.5 タスク5: JPA用のGlassFish Serverの設定

GlassFish Serverアプリケーション開発ガイドのJava永続性プロバイダの構成に関する項には、JPAを利用するアプリケーションを実行するGlassFishサーバーを設定する際のサーバー固有の考慮事項が説明されています。

これでは、次のトピックについて詳しく説明しています。

- データベース接続プロパティの詳細は、アプリケーション用のデータベースの指定に関する項

- アプリケーション用にデフォルトまたはデフォルトでない永続性プロバイダを設定する方法の詳細は、アプリケーション用の永続性プロバイダの指定に関する項

- デフォルトの永続性プロバイダの主キーの生成のデフォルトの詳細は、主キーの生成のデフォルトに関する項

- スキーマの自動生成を管理する注釈およびオプションの詳細は、スキーマの自動生成に関する項

- Java Persistence APIの使用に影響する制限およびパフォーマンスの最適化の詳細は、制限および最適化に関する項

4.2.6 タスク6: アプリケーションの作成

EclipseLinkをJPA永続性プロバイダとして使用するアプリケーションを作成するには、Java EE IDE開発環境を開発に使用すると便利です。たとえば、JDeveloper、Oracle Enterprise Pack for EclipseおよびNetBeansにはすべて、EclipseLinkのサポートを含む高度なJava EE開発ツールが用意されています。『Oracle TopLinkの理解』の主要なツールに関する項を参照してください。

アプリケーションの記述方法の詳細は、これらのトピックについて、『Oracle GlassFish Serverアプリケーション開発ガイド』のJava永続性プロバイダの構成に関する章を参照してください。

4.2.7 タスク7: GlassFish Serverに対するアプリケーションのデプロイ

GlassFish Serverへのデプロイの詳細は、GlassFish Server管理コンソール・オンライン・ヘルプのアプリケーションまたはモジュールのデプロイに関する項、エンタープライズ・アプリケーションのデプロイに関する項、およびWebアプリケーションのデプロイに関する項を参照してください。『Oracle GlassFish Serverアプリケーション開発ガイド』も参照してください。

4.2.8 タスク8: アプリケーションの実行

デプロイされたアプリケーションをGlassFish Server管理コンソールから起動する手順の詳細は、GlassFish Server管理コンソール・オンライン・ヘルプのアプリケーション・クライアントの起動に関する項、およびアプリケーションの起動に関する項を参照してください。

4.2.9 タスク9: アプリケーションの監視

GlassFish Serverには、アプリケーションのヘルスおよびパフォーマンスを追跡するモニタリング・サービスが用意されています。コンソールからアプリケーションを監視する方法の詳細は、GlassFish Server管理コンソール・オンライン・ヘルプの監視に関する項、およびデータの監視に関する項を参照してください。コマンドラインからアプリケーションを監視する方法の詳細は、『Oracle GlassFish Server管理ガイド』のモニタリング・サービスの管理に関する項を参照してください。

4.3 その他の参考資料

この章のソリューションが実装されているその他のテクノロジおよびツールの詳細は、次の参考資料を参照してください。

- 『Oracle GlassFish Server管理ガイド』

- Oracle GlassFish Serverアプリケーション・デプロイメント・ガイド

- 『Oracle GlassFish Serverアプリケーション開発ガイド』

- Oracle GlassFish Server 3.1.2から3.1.2.2のドキュメント・ライブラリ

5 JBoss 7 Application ServerでTopLinkを使用する方法

この章では、Oracle TopLinkをJBoss Application Server 7.1にデプロイされたアプリケーションの永続性プロバイダとして使用する方法を説明します。

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

- 5.1項「ソリューションの概要」

- 5.2項「ソリューションの実装」

- 5.3項「その他の参考資料」

ユース・ケース

TopLinkは、JBoss Application Serverを含む多くの一般的なJava EEアプリケーション・サーバーで使用できます。

解決方法

EclipseLinkランタイムを使用するようJBossを構成して、EclipseLinkのAPIを使用して開発されたアプリケーションをデプロイします。

コンポーネント

- TopLink 12cリリース1 (12.1.2)以上。

注意:

TopLinkのコア機能は、オープン・ソースのEclipse Foundationの永続性フレームワークであるEclipseLinkによって提供されています。EclipseLinkでは、Java Persistence API (JPA)、Java Architecture for XML Binding (JAXB)、および標準に基づいたその他の永続性テクノロジと、それらの標準の拡張が実装されます。TopLinkには、EclipseLinkのすべてに加え、Oracleの追加機能が含まれています。

- JBoss Application Server 7.x。

- Oracle Database、Oracle Express、MySQL、JBoss Application Serverに組み込まれているHSQLデータベースなどの対応するJava Database Connectivity (JDBC)データベース。

5.1 ソリューションの概要

JBoss Application Serverには、Java Platform, Enterprise Edition (Java EE)が実装されます。JBoss 7ではJava EE 6が完全にサポートされていますが、JBoss 6では公式にはJava EE 6 Webプロファイルのみがサポートされています。

JBossでEclipseLinkがサポートされるように構成すると、Java Persistence API (JPA)、Java Architecture for XML Binding (JAXB)およびそれらのテクノロジに対するEclipseLinkの拡張、またリレーショナル・データベースのアーティファクトにアクセスするWebサービスを介したEclipseLink Database Web Services (DBWS)を完全にサポートするEclipseLinkの利益を享受できます。

5.2 ソリューションの実装

JBoss Application Server 7でEclipseLinkのアプリケーションを開発、デプロイおよび実行するには、EclipseLinkをJBossのモジュールとして作成する必要があります。また、アプリケーションを実行するために、JDBCドライバなどその他のモジュールも作成する必要があります。

この項では、JBoss 7.1でEclipseLinkを使用するための次のタスクについて説明します。

- タスク1: 前提条件

- タスク2: JBossのモジュールとしてのEclipseLinkの構成

- タスク3: JBossのモジュールとしてのojdbc6.jarの追加

- タスク4: ドライバ定義およびデータ・ソースの作成

- タスク5: ユーザーの作成

- タスク6: JBossのプロパティの変更

- タスク7: その他の要件

- タスク8: JBossの起動

5.2.1 タスク1: 前提条件

次のコンポーネントがインストールされていることを確認します。

- JBossバージョン7以上。ここで説明する手順は、JBossリリース7.1.1のものです。
http://www.jboss.org/jbossas/downloads/からJBossをダウンロードします。JBossのバージョンは、Certified Java EE6となっている必要があります。推奨は、Version 7.1.1以上です。

- TopLink 12cリリース1 (12.1.2)以上。
http://www.oracle.com/technetwork/middleware/toplink/downloads/index.htmlからTopLinkをダウンロードします。

- Oracle Database、Oracle Express、MySQL、JBoss Application Serverに組み込まれているいるHSQLデータベースを含む任意の対応するJava Database Connectivity (JDBC)データベース。

注意:

Oracle XML DB (XDB)およびJBoss Application Serverは、いずれもデフォルトでポート8080を使用します。localhostなど同じURIで両方が使用されるようになっている場合、いずれか一方が8081などの別のポートを使用するよう再構成する必要があります。

Oracle Databaseについては、http://www.oracle.com/technetwork/database/enterprise-edition/overview/index.htmlを参照してください。Oracle Database, Express Editionについては、http://www.oracle.com/technetwork/database/express-edition/overview/index.htmlを参照してください。MySQLについては、http://www.oracle.com/us/products/mysql/index.htmlを参照してください。組込みHSQLデータベースの詳細は、JBossのドキュメントを参照してください。

- 必須ではありませんが、Java開発環境(IDE)を開発に使用すると便利です。JDeveloper、Oracle Enterprise Pack for EclipseおよびNetBeansなどすべてに、TopLinkをサポートする高度なJava EE開発ツールが用意されています。
JDeveloperについては、http://www.oracle.com/technetwork/developer-tools/jdev/downloads/index.htmlを参照してください。Oracle Enterprise Pack for Eclipseについては、http://www.oracle.com/technetwork/developer-tools/eclipse/overview/index.htmlを参照してください。NetBeansについては、http://www.oracle.com/us/products/tools/050845.htmlを参照してください。

5.2.2 タスク2: JBossのモジュールとしてのEclipseLinkの構成

JBossのモジュールとしてEclipseLinkを構成するには、次の手順を実行します。

1. 次のようにディレクトリを作成します。

JBOSS_ HOME\modules\org\eclipse\persistence\main

2. 手順1で作成したディレクトリにeclipselink.jarをコピーします。(eclipselink.jarファイルは、TopLinkのクイック・インストーラによって作成されたoracle_common\modules\oracle.toplink_ver_noディレクトリにあります。)

3. 手順1で作成したディレクトリに、次の内容でmodule.xmlファイルを作成します。

<module xmlns="urn:jboss:module:1.1" name="org.eclipse.persistence">
<resources>
<resource-root path="eclipselink.jar"/>
<!-- Insert resources here -->
</resources>
<dependencies>
<module name="javax.api"/>
<module name="javax.persistence.api"/>
<module name="javax.transaction.api"/>
<module name="javax.validation.api"/>
<module name="javax.xml.bind.api"/>
<module name="org.antlr"/>
<module name="org.apache.commons.collections"/>
<module name="org.dom4j"/>
<module name="org.javassist"/>
<module name="org.jboss.logging"/>
<module name="com.oracle.ojdbc6"/>
</dependencies>
</module>

5.2.3 タスク3: JBossのモジュールとしてのojdbc6.jarの追加

Oracle Thinドライバojdbc6.jarをJBossにモジュールとして追加するには、次の手順を実行します。

1. モジュール・ディレクトリを作成します。

JBOSS_ HOME\modules\com\oracle\ojdbc6\main

2. 手順1で作成したモジュール・ディレクトリにojdbc6.jarをコピーします。

3. 手順1で作成したモジュール・ディレクトリに、次の内容でmodule.xmlファイルを作成します。

<module xmlns="urn:jboss:module:1.1" name="com.oracle.ojdbc6">
<resources>
<resource-root path="ojdbc6.jar"/>
<!-- Insert resources here -->
</resources>
<dependencies>
<module name="javax.api"/>
</dependencies>
</module>

5.2.4 タスク4: ドライバ定義およびデータ・ソースの作成

ドライバの定義およびデータ・ソースを作成します。

次の手順では、standalone.xml構成ファイルを使用してスタンドアロン・モードでJBossを構成する手順を説明します。domain.xmlを使用して、ドメイン・モードで実行するようJBossを構成する方法の詳細は、JBossのドキュメントを参照してください。

1. スタンドアロンの構成ファイルJBOSS_ HOME\standalone\configuration\standalone.xmlで次を探します。
<subsystem xmlns="urn:jboss:domain:datasources:1.0">

2. そのセクションで、データ・ソースを構成します。次に、Oracle JDBC Thinドライバを使用したOracle Databaseの構成を示します。その他のデータ・ソースの構成手順については、JBossのドキュメントを参照してください。

<subsystem xmlns="urn:jboss:domain:datasources:1.0">
<datasources>
<datasource jndi-name="java:/EclipseLinkDS"
pool-name="EclipseLinkDS"
enabled="true"
jta="true"
use-java-context="true"
use-ccm="true">
<connection-url>jdbc:oracle:thin:node_name.example.com:1521:TOPLINK</connection-url>
<driver>oracle</driver>
<transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
<pool>
<prefill>true</prefill>
<use-strict-min>false</use-strict-min>
<flush-strategy>FailingConnectionOnly</flush-strategy>
</pool>
<security>
<user-name>Smith</user-name>
<password>password</password>
</security>
</datasource>
<driver name="oracle" module="com.oracle.ojdbc6">
<xa-datasource-class>oracle.jdbc.OracleDriver</xa-datasource-class>
</driver>
</datasources>
</subsystem>

5.2.5 タスク5: ユーザーの作成

JBoss Application Server 7.1以降、JNDIツリーへのリモート・アクセスがデフォルトでセキュリティ保護されており、ログイン資格証明を提供する必要があるため、アプリケーション・ユーザーを最初に作成する必要があります。したがって、サーバーにアプリケーションをデプロイするには、最低でもアプリケーション・ユーザーを作成する必要があります。JNDIツリーを参照するなどの管理タスクにJBoss管理コンソールを使用するためにも、管理者ユーザーを作成する必要があります。

ユーザーの資格証明を作成するには、JBOSS_HOME\bin\にある、JBossのadd-user.batユーティリティを使用します。

JBoss Application Serverでのセキュリティの詳細は、JBossのドキュメントを参照してください。

5.2.6 タスク6: JBossのプロパティの変更

次のようにJBossのプロパティを変更します。

## JBoss-7.x
server.factory=org.jboss.naming.remote.client.InitialContextFactory
java.naming.factory.url.pkgs=org.jboss.ejb.client.naming
server.depend=jboss-client.jar
jboss.server=${jboss.home}/standalone
server.lib=${jboss.home}/bin/client
server.url=remote://localhost:4447
server.user=usera
server.pwd=passworda
jboss.naming.client.ejb.context=true

5.2.7 タスク7: その他の要件

1. \libディレクトリの下にearにjunit.jarを追加します。

2. JBossのクラスロードの問題のために、persistence.xmlにエンティティ・クラスをすべて列挙する必要があります。<class>要素またはグローバル<exclude-unlisted-classes>false</exclude-unlisted-classes>要素を使用します。

3. jndi.propertiesおよびjboss-ejb-client.propertiesの両方のプロパティをクライアントのクラスパスに追加します。

5.2.8 タスク8: JBossの起動

(サーバーが1つのみの構成の場合は)standalone.batまたは(クラスタ環境の場合は)domain.batファイルをJBOSS_ HOME\bin\で実行し、JBossを起動します。

JBossを構成および起動する別の方法については、JBossのドキュメントを参照してください。

5.3 その他の参考資料

この章のソリューションが実装されているその他のテクノロジおよびツールの詳細は、次の参考資料を参照してください。

- http://www.jboss.orgのJBossコミュニティ。

6 IBM WebSphere Application ServerでTopLinkを使用する方法

この章では、Oracle TopLinkをIBM WebSphere Application Serverにデプロイされたアプリケーションの永続性プロバイダとして使用する方法を説明します。

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

- 6.1項「ソリューションの概要」

- 6.2項「ソリューションの実装」

- 6.3項「その他の参考資料」

ユース・ケース

TopLinkは、WebSphere Application Serverを含む多くの一般的なJava EEアプリケーション・サーバーで使用できます。

解決方法

WebSphereを構成し、EclipseLinkランタイムを使用して、EclipseLink APIを使用して開発されたアプリケーションをデプロイします。

コンポーネント

- TopLink 12cリリース1 (12.1.2)以上。

注意:

TopLinkのコア機能は、オープン・ソースのEclipse Foundationの永続性フレームワークであるEclipseLinkによって提供されています。EclipseLinkでは、Java Persistence API (JPA)、Java Architecture for XML Binding (JAXB)、および標準に基づいたその他の永続性テクノロジと、それらの標準の拡張が実装されます。TopLinkには、EclipseLinkのすべてに加え、Oracleの追加機能が含まれています。

- WebSphere Application Server 7以上。ここで説明する手順は、WebSphere 8.5のものです。

- Oracle Database、Oracle Express、MySQL、WebSphere Application Serverに組み込まれているいるDerbyデータベースなどの対応するJava Database Connectivity (JDBC)データベース。

6.1 ソリューションの概要

WebSphere Application Serverでは、Java Platform, Enterprise Edition (Java EE)が実装されます。WebSphere V8.5はJava EE 6を完全にサポートし、プラグインを介してJava Platform, Standard Edition (Java SE) 7をサポートできます。

EclipseLinkをサポートするようにWebSphereを構成することにより、EclipseLinkが完全にサポートしているJava Persistence API (JPA)およびEclipseLinkの多くの拡張を利用するアプリケーションを作成およびデプロイできます。

6.2 ソリューションの実装

IBM WebSphereでEclipseLinkアプリケーションを開発、デプロイおよび実行するには、EclipseLinkを含む様々なモジュールをWebSphereに追加し、WebSphereの様々な局面を構成してEclipseLinkをサポートするようにする必要があります。

この項では、IBM WebSphere Version 7以上でEclipseLinkを使用するその他のタスクについて説明しています。

- タスク1: 前提条件

- タスク2: 永続性ユニットの構成

- タスク3: EclipseLinkを使用するためのサーバーおよびアプリケーションの構成

6.2.1 タスク1: 前提条件

次のコンポーネントがインストールされていることを確認します。

- IBM WebSphere, Version 7以上。ここで説明する手順は、WebSphereバージョン8.5のものです。
http://www-01.ibm.com/software/webservers/appserv/was/からIBM WebSphereを入手します。

- TopLink 12cリリース1 (12.1.2)以上。
http://www.oracle.com/technetwork/middleware/toplink/downloads/index.htmlからTopLinkをダウンロードします。

次のファイルを使用します。

- TopLinkクイック・インストーラによって作成されたoracle_common\modules\oracle.toplink_ver_noディレクトリにあるeclipselink.jar

- TopLinkのクイック・インストーラによって作成されたoracle_common\modulesディレクトリにあるjavax.persistence_ver_no.jar

6.2.2 タスク2: 永続性ユニットの構成

EclipseLinkを永続性プロバイダとして、またWebSphereをターゲット・サーバーとして使用するには、永続性ユニットを構成します。

例6-1に、コンテナで管理される永続性ユニットの構成例を示します。

例6-1 コンテナで管理される永続性ユニットのpersistence.xmlの例

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence persistence_1_0.xsd"
version="1.0">
<persistence-unit name="default" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/EclipseLinkDS</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="eclipselink.target-server" value="WebSphere_7"/>
<property name="eclipselink.target-database"
value="org.eclipse.persistence.platform.database.oracle.Oracle11Platform"/>
<property name="eclipselink.validate-existence" value="true"/>
<property name="eclipselink.weaving" value="true"/>
<property name="eclipselink.logging.level" value="FINEST"/>
</properties>
</persistence-unit>
</persistence>

例6-2に、アプリケーションで管理される永続性ユニットの構成例を示します。

例6-2 アプリケーションで管理される永続性ユニットのサンプルのpersistence.xml

<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence persistence_1_0.xsd" version="1.0">
<persistence-unit name="default" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<non-jta-data-source>jdbc/ELNonJTADS</non-jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="eclipselink.target-server" value="WebSphere_7"/>
<property name="eclipselink.target-database"
value="org.eclipse.persistence.platform.database.oracle.Oracle11Platform"/>
<property name="eclipselink.validate-existence" value="true"/>
<property name="eclipselink.weaving" value="true"/>
<property name="eclipselink.logging.level" value="FINEST"/>
</properties>
</persistence-unit>
</persistence>

前述の2例について、次を考慮してください。

- eclipselink.target-server値WebSphere_7は、WebSphere Application Serverバージョン7以上用で使用されています。

- 永続性スキーマのバージョンpersistence_1_0.xsd" version="1.0"はJPA 1とJPA 2の両方に指定して動作します。JPA 2.nのみのアプリケーションでは、バージョンをpersistence_2_0.xsd" version="2.n"に変更します(WebSphereでは、WebSphere Application Server 7.0.0.9以上でJPA 2をサポートするようになりました)。

6.2.3 タスク3: EclipseLinkを使用するためのサーバーおよびアプリケーションの構成

次は、アプリケーション・サーバーでEclipseLinkを使用する典型的なシナリオです。

- EclipseLinkをグローバルで利用できるようにするためのサーバーの変更

- アプリケーションEARへのEclipseLinkのパッケージ

- WARへのEclipseLinkのパッケージ

6.2.3.1 EclipseLinkをグローバルで利用できるようにするためのサーバーの変更

コンテナおよびアプリケーションで管理される永続ユニットのいずれも、次のいずれかの方法でグローバルにEclipseLinkで使用できるようにできます。

- オプション1: グローバルに共有するライブラリの作成(推奨)

- オプション2: サーバー・ライブラリ拡張としてのEclipseLinkの追加

オプション1: グローバルに共有するライブラリの作成(推奨)

1. 次のファイルを含むグローバルに共有するライブラリを作成します。

- eclipselink.jar
このファイルを、TopLinkクイック・インストーラによって作成されたTOPLINK_INSTALLATION\oracle_common\modules\oracle.toplink_ver_noディレクトリから探します。

- xmlparserv2.jar
このファイルをクイック・インストーラで作成されたTOPLINK_INSTALLATION\toplink\modulesディレクトリから探します。

- JPAでNCHAR、XMLTYPEおよびMDSYS.SDO_GEOMETRYなどのOracle Databaseの機能を使用する場合、共有ライブラリにxdb.jarおよびsdoapi.jarも含める必要があります。これらのファイルはOracle Databaseの配布内にあります。

WebSphereを使用して共有ライブラリを簡単に作成する方法の詳細は、WebSphereのドキュメントを参照してください。

2. 共有ライブラリをアプリケーションと関連付けます。
WebSphereを使用して共有ライブラリとアプリケーションを関連付ける方法については、WebSphereのドキュメントを参照してください。

オプション2: サーバー・ライブラリ拡張としてのEclipseLinkの追加

サーバー・ライブラリの拡張としてEclipseLinkを追加するには、前述のオプション1にあるeclipselink.jarとその他のJARファイルをWAS_HOME\lib\extディレクトリにコピーします。

6.2.3.2 アプリケーションEARへのEclipseLinkのパッケージ

サーバー構成を変更せず、eclipselink.jarをアプリケーションEARに追加して、コンテナで管理される永続性を実装できます。この場合、永続性ユニットはステートレス・セッションBeanへの@PersistenceContextエンティティ・マネージャ・プロキシの挿入で管理されています。次に、このアプローチの例を示します。

1. アプリケーションEARの次の場所にeclipselink.jarを追加します。
EAR_archive/APP-INF/lib/

2. このパスを、次のようにEJB JARのejbModule/META-INF/MANIFEST.MFファイルのeclipselink.jarに追加します。

Manifest-Version: 1.0
Class-Path: APP-INF/lib/eclipselink.jar

これは、エンティティの場所のルートのマニフェストで、この場合はejb.jar.の一部です。

3. アプリケーションのクラス・ローダーで最初にクラスがロードされるよう、クラス・ローダーを構成します。

4. アプリケーションをデプロイして起動します。手順については、IBM WebSphereのドキュメントを参照してください。

6.2.3.3 WARへのEclipseLinkのパッケージ

前述の2つのシナリオで説明するとおり、コンテナで管理される永続性を実装できない場合、アプリケーションで管理されるエンティティ・マネージャを作成できます。この場合、ライブラリのすべての構成およびクラスローダーの範囲の変更をEAR自体内で行う必要があります。

1. 次の場所のWebアプリケーション・アーカイブ(WAR)ファイルに、eclipselink.jarおよびjavax.persistence_ver_no.jarを追加します。
WAR_archive/WEB-INF/lib/

2. アプリケーションのクラス・ローダーで最初にクラスがロードされるよう、アプリケーションのクラス・ローダーの順番を構成します。管理コンソールを使用して、クラス・ローダーの順番を設定する手順の詳細については、WebSphereのドキュメントを参照してください。

3. アプリケーションをデプロイして起動します。手順については、IBM WebSphereのドキュメントを参照してください。

6.3 その他の参考資料

この章のソリューションが実装されているその他のテクノロジおよびツールの詳細は、次の参考資料を参照してください。

- http://www-01.ibm.com/software/webservers/appserv/was/のWebSphere Application Server。

7 ネイティブTopLinkからの移行

この章では、TopLinkのネイティブなオブジェクト・リレーショナル・マッピング(ORM) APIを現在のEclipseLink APIに移行する方法を説明します。

TopLink 11gリリース1 (11.1.1)以降、EclipseLinkライブラリはOracle TopLinkのコア・ライブラリとなっています。

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

- 7.1項「ソリューションの概要」

- 7.2項「ソリューションの実装」

- 7.3項「その他の参考資料」

ユース・ケース

アプリケーションをアップグレードして、使用しているTopLinkにネイティブの以前のORMを、現在の実装であるEclipseLink ORMを使用するようにしたいと開発者は考えています。

解決方法

この章の手順に従って、アプリケーションをアップグレードします。

コンポーネント

- TopLink 12cリリース1 (12.1.2)以上。

注意:

TopLinkのコア機能は、オープン・ソースのEclipse Foundationの永続性フレームワークであるEclipseLinkによって提供されています。EclipseLinkでは、Java Persistence API (JPA)、Java Architecture for XML Binding (JAXB)、および標準に基づいたその他の永続性テクノロジと、それらの標準の拡張が実装されます。TopLinkには、EclipseLinkのすべてに加え、Oracleの追加機能が含まれています。

- (オプション) EclipseLink Workbench。

7.1 ソリューションの概要

ネイティブTopLink ORMとは、Java Persistence API (JPA)がオブジェクト・リレーショナル・マッピングAPIを標準化する前に、TopLinkで展開された、API、構成ファイル、オブジェクト・リレーショナル・マッピング用のツールを指します。JPAは、TopLink EssentialsとしてOracle TopLink 10g (10.1.3.1.0)で完全にサポートされるようになりました。ただし、ネイティブTopLinkもサポートされ続けています。

TopLink 11g (11.1.1)リリースより前では、Oracleでは、Eclipse FoundationにTopLink JPAおよびネイティブTopLinkを含むTopLinkのソース・コードを提供し、これを基にして、オープンソースのEclipseLink永続性サービス・プロジェクトの基礎が形成されました。その後、TopLink 11gリリース1 (11.1.1)で、OracleはTopLinkにTopLinkのコア機能を提供するEclipseLinkを含めるようになりました。

TopLinkバージョン11.1.1.0.0から11.1.1.6.0を使用するTopLink開発者は、Oracle独自のtoplink.jarまたはEclipseLink eclipselink.jarのいずれかで、ネイティブTopLink ORMにアクセスできます。toplink.jarのクラスは、名前がoracle.toplink.*で開始するパッケージです。eclipselink.jarでは、これらのパッケージ名は、かわりにorg.eclipselink.persistenceで開始します。

注意:

toplink.jarファイルはTopLink 11gで非推奨となり、TopLink 12cでは出荷されなくなっています。TopLink 11gでは、oracle.toplink.*から移行することをお薦めします。

toplink.jarのoracle.toplink.*パッケージを使用するアプリケーションを、eclipselink.jarのorg.eclipselink.persistence.パッケージを使用するよう移行できます。アプリケーションの機能は同じですが、eclipselink.jarに移行することにより、最新のコード・ベースが得られます。移行すると、他のTopLink機能を利用できるようになり、アプリケーションでJPAまたは現在のTopLinkのバージョンの他の永続性サービスを使用する準備を整えることができます。

この章では、スタンドアロンのTopLinkにパッケージされている名前変更ツールを使用して、アプリケーションのパッケージ名を簡単に変更し、現在のコード・ベースに移行するために必要なその他のアクションを実行する方法を説明します。

注意:

この章の説明に従うと、アプリケーションが更新され、現在のEclipseLinkのコード・ベースを使用できるようになります。これを実行した場合、当初実装したアプリケーションの設計および機能が維持されます。ただし、これらの手順では、ネイティブTopLinkベース・アプリケーションでJPAまたは現在のTopLinkのバージョンのその他の任意の永続性サービスを使用するよう変換する方法は説明していません。この情報については、TopLinkのその他のドキュメントを参照してください。

7.2 ソリューションの実装

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

- 7.2.1項「タスク1: 前提条件」

- 7.2.2項「タスク2: 非推奨および削除されたネイティブAPIの置換」

- 7.2.3項「タスク3: パッケージの名前変更」

- 7.2.4項「タスク4: XML構成ファイルの変換」

- 7.2.5項「タスク5: Oracle TopLink Workbenchプロジェクトの変換(オプション)」

7.2.1 タスク1: 前提条件

- TopLink 12c (12.1.2)以上。
11g以上のTopLinkのすべてのダウンロードには、この章で説明している名前変更ツールが含まれています。

注意:

この名前変更ツールは、Oracle WebLogic ServerまたはOracle Glassfishに組み込まれているバージョンのTopLinkには含まれません。スタンドアロンのTopLinkインストーラをダウンロードする必要があります。

http://www.oracle.com/technetwork/middleware/toplink/downloads/index.htmlからTopLinkをダウンロードします。インストール手順については、第2章「Oracle TopLinkのインストール」を参照してください。

- (オプション) EclipseLink Workbench。EclipseLink WorkbenchはEclipseLinkのダウンロードに含まれています。http://www.eclipse.org/eclipselink/downloads/のEclipseLinkのダウンロード・ページを参照してください。

7.2.2 タスク2: 非推奨および削除されたネイティブAPIの置換

TopLink 11gリリース1 (11.1.1)以前のリリースで非推奨であったAPIは、EclipseLinkでは削除されているので、現在のバージョンのTopLinkには含まれていません。アプリケーションでこれらの非推奨のAPIやすでにTopLinkで置換または削除されているAPIを使用している場合、アプリケーションで現在のAPIを使用するよう更新する必要があります。

次の項では、推奨される代替とともに、置換および削除されたAPIを示します。

- 7.2.2.1項「置換されたAPI」

- 7.2.2.2項「非推奨のAPI」

- 7.2.2.3項「削除されたAPI」

注意:

推奨される代替がoracle.toplink.*パッケージに含まれる場合、7.2.3項「タスク3: パッケージの名前変更」の説明に従って、パッケージ名も変更する必要があります。

7.2.2.1 置換されたAPI

次の表に、TopLink 11gリリース1 (11.1.1.1.)以上で削除されたAPIを示します。この表に示す代替のAPIを使用するようにしてください。

- 表7-1「changetracking (oracle.toplink.descriptors.*)」

- 表7-2「databaseaccess (oracle.toplink.internal*)」

- 表7-3「jdo (oracle.toplink.*)」

- 表7-4「mappings (oracle.toplink.*)」

- 表7-5「objectrelational (oracle.toplink.*)」

- 表7-6「oraclespecific (oracle.toplink.*)」

- 表7-7「publicinterface (oracle.toplink.*)」

- 表7-8「sdk (oracle.toplink.*)」

- 表7-9「entitymanager (oracle.toplink.sessions.*)」

- 表7-10「sessionconfiguration (oracle.toplink.tools.*)」

- 表7-11「xml (oracle.toplink.*)」

- 表7-12「XMLCommandConverter (oracle.toplink.*)」

- 表7-13「Remote Protocols (oracle.toplink.*)」

- 表7-14「BEA WebLogic 6.1に対するEJBマッピング」

- 表7-15「mappings (oracle.toplink.*)」

- 表7-16「descriptors (oracle.toplink.*)」

表7-1 changetracking (oracle.toplink.descriptors.*)

クラス名

メソッド名

代替のAPI

ChangeTracker

getTopLinkPropertyChangeListener

._persistence_getPropertyChangeListener

ChangeTracker

setTopLinkPropertyChangeListener(PropertyChangeListener)

_persistence_setPropertyChangeListener(PropertyChangeListener)

表7-2 databaseaccess (oracle.toplink.internal*)

クラス名

メソッド名

代替のAPI

.*Platform

完全なクラス名

oracle.toplink.platform.database.*Platform

表7-3 jdo (oracle.toplink.*)

クラス名

メソッド名

代替のAPI

.jdo

完全なパッケージ名

なし

表7-4 mappings (oracle.toplink.*)

クラス名

メソッド名

代替のAPI

TypeConversionMapping

完全なクラス名

.mappings.converters.TypeConversionConverter

ObjectTypeMapping

完全なクラス名

.mappings.converters.ObjectTypeConverter

SerializedObjectMapping

完全なクラス名

.mappings.converters.SerializedObjectConverter

表7-5 objectrelational (oracle.toplink.*)

クラス名

メソッド名

代替のAPI

Oracle8Platform

完全なクラス名

oracle.toplink.platform.database.oracle.Oracle8Platform

表7-6 oraclespecific (oracle.toplink.*)

クラス名

メソッド名

代替のAPI

.oraclespecific.NCharacter

完全なクラス名

.platform.database.oracle.NCharacter

.oraclespecific.NClob

完全なクラス名

.platform.database.oracle.NClob

.oraclespecific.NClob

完全なクラス名

.platform.database.oracle.NClob

.oraclespecific.Oracle8Platform

完全なクラス名

.platform.database.oracle.Oracle8Platform

.oraclespecific.Oracle9Specific 注 1

完全なクラス名

.platform.database.oracle.Oracle9Specific

.oraclespecific.TopLinkXMLType 注 2

完全なクラス名

なし

注 1 oracle.toplink.oraclespecific.Oracle9Specificは内部のパッケージに移動され、oracle.toplink.internal.platform.database.oracle.Oracle9Specificに名前変更されています。oracle.toplink.oraclespecific.Oracle9Specificの代替のパブリックAPIは、oracle.toplink.platform.database.oracle.Oracle9Specificです。

注 2 oracle.toplink.oraclespecific.TopLinkXMLTypeはその他のもののクラスで代替APIがありません。

表7-7 publicinterface (oracle.toplink.*)

クラス名

メソッド名

代替のAPI

DatabaseRow

完全なクラス名

.sessions.DatabaseRecord

DatabaseSession 注 1

完全なクラス名

.sessions.DatabaseSession

Descriptor

完全なクラス名

.descriptors: ClassDescriptor、RelationalDescriptor

DescriptorEvent

完全なクラス名

.descriptors.DescriptorEvent

DescriptorEventListener

完全なクラス名

.descriptors: 新しいインタフェースでは、古いインタフェースを拡張しません

DescriptorEventManager

完全なクラス名

.descriptors

DescriptorQueryManager

完全なクラス名

.descriptors

InheritancePolicy

完全なクラス名

.descriptors

Session注 2

完全なクラス名

.sessions.Session

UnitOfWork注 3

完全なクラス名

.sessions.UnitOfWork

注 1 oracle.toplink.publicinterface.DatabaseSessionは内部のパッケージに移動され、oracle.toplink.internal.sessions.DatabaseSessionImplに名前変更されています。oracle.toplink.publicinterface.DatabaseSessionの代替のパブリックAPIは、oracle.toplink.sessions.DatabaseSessionです。

注 2 oracle.toplink.publicinterface.Sessionは内部のパッケージに移動され、oracle.toplink.internal.sessions.AbstractSessionImplに名前変更されています。oracle.toplink.publicinterface.Sessionの代替のパブリックAPIは、oracle.toplink.sessions.Sessionです。

注 3 oracle.toplink.publicinterface.UnitOfWorkは内部のパッケージに移動され、oracle.toplink.internal.sessionl.UnitOfWorkImplに名前変更されています。oracle.toplink.publicinterface.UnitOfWorkの代替のパブリックAPIはoracle.toplink.sessions.UnitOfWorkです。

表7-8 sdk (oracle.toplink.*)

クラス名

メソッド名

代替のAPI

.sdk

完全なパッケージ名

.eis

表7-9 entitymanager (oracle.toplink.sessions.*)

クラス名

メソッド名

代替のAPI

すべてのクラス

すべてのメソッド

JPA: 7.2.2.4.1項「JPA永続性プロバイダの実装」を参照

表7-10 sessionconfiguration (oracle.toplink.tools.*)

クラス名

メソッド名

代替のAPI

WASXMLLoader

すべてのメソッド

なし

表7-11 xml (oracle.toplink.*)

クラス名

メソッド名

代替のAPI

.xml

完全なパッケージ名

.ox

.xmlstream

完全なパッケージ名

.ox

.xml.tools

完全なパッケージ名

.ox

.xml.xerces

完全なパッケージ名

.ox

.xml.zip

完全なパッケージ名

.ox

表7-12 XMLCommandConverter (oracle.toplink.*)

クラス名

メソッド名

代替のAPI

.remotecommand.XMLCommandConverter

完全なクラス名

なし

.transform.xml.XMLSource

完全なクラス名

なし

.transform.xml.XMLResult

完全なクラス名

なし

.internal.localization.i18n.ExceptionLocalizationResource

error_loading_resources

なし

.internal.localization.i18n.ExceptionLocalizationResource

error_parsing_resources

なし

.internal.localization.i18n.ExceptionLocalizationResource

unexpect_argument

なし

表7-13 Remoteプロトコル(oracle.toplink.*)

クラス名

メソッド名

代替のAPI

.remote.corba.orbix

完全なパッケージ名

なし

.remote.corba.visibroker

完全なパッケージ名

なし

.remote.ejb

完全なパッケージ名

なし

.tools.sessionconfiguration.TopLinkSessionsFactory

orbix、visibrokerおよびejbパッケージ内の任意のJNDIClusteringServiceに対する参照。

なし

.tools.sessionconfiguration.DTD2SessionConfigLoader

orbix、visibrokerおよびejbパッケージ内の任意のJNDIClusteringServiceに対する参照。

なし

.tools.sessionconfiguration.model.clustering.VisibrokerCORBAJNDIClusteringConfig

完全なクラス名

なし

.tools.sessionconfiguration.model.clustering.OrbixCORBAJNDIClusteringConfig

完全なクラス名

なし

.tools.sessionconfiguration.model.clustering.EJBJNDIClusteringConfig

完全なクラス名

なし

.tools.sessionconfiguration.XMLSessionConfigProject

orbix、visibrokerおよびejbパッケージ内の任意のJNDIClusteringServiceに対する参照。

なし

表7-14 BEA WebLogic 6.1に対するEJBマッピング

クラス名

メソッド名

代替のAPI

toplink-cmp-bean_name.xml

なし

internal.ejb.cmp.wls11.CMPDeployer.readTypeSpecificData()の先頭に警告が追加されます

7.2.2.2 非推奨のAPI

次の表にTopLink 11gリリース1 (11.1.1)リリースより前に非推奨となり、したがって現在のリリースではEclipseLinkライブラリに置き換えられたために削除されたAPIを示します。かわりに示した代替のAPIを使用してください。

注意:

非推奨となったクラスと移動したクラスの名前は同じなので、古いパッケージと新しいパッケージの両方からimport *を使用してクラスをインポートすると、コンパイル・エラーが発生します。これらのエラーを回避するには、完全修飾されたパッケージ名でimportを使用します。

- 表7-15「mappings (oracle.toplink.*)」

- 表7-16「descriptors (oracle.toplink.*)」

表7-15 mappings (oracle.toplink.*)

クラス名

メソッド名

代替のAPI

OneToOneMapping

useJoining

ForeignReferenceMapping.setJoinFetch(int)

表7-16 descriptors (oracle.toplink.*)

クラス名

メソッド名

代替のAPI

ClassDescriptor

addMultipleTableForeignKeyField

addForeignKeyFieldForMultipleTable

ClassDescriptor

addMultipleTablePrimaryKeyField

addForeignKeyFieldForMultipleTable

ClassDescriptor

addMultipleTablePrimaryKeyFieldName

addForeignKeyFieldNameForMultipleTable

ClassDescriptor

addMultipleTableForeignKeyFieldName

addForeignKeyFieldNameForMultipleTable

7.2.2.3 削除されたAPI

次のクラスは、TopLink 11gリリース1 (11.1.1)より前のリリースで削除されています。

- OTSTransactionController

- OTSSynchronizationListener

- OracleSequenceDefinition(かわりにSequenceObjectDefinitionを使用)

- TimeTenSequenceDefinition(かわりにSequenceObjectDefinitionを使用)

7.2.2.4 その他のAPIの変更

APIに対するその他の変更は次のとおりです。

- 7.2.2.4.1項「JPA永続性プロバイダの実装」

- 7.2.2.4.2項「セッション・ファイナライザのデフォルトでの無効化」

- 7.2.2.4.3項「戻し型VectorおよびHashtableのListまたはMapへの変更」

7.2.2.4.1 JPA永続性プロバイダの実装

TopLink 11g (11.1.1)以上のリリースでは、永続性プロバイダは、eclipselink.jarのパッケージに実装されています。たとえば次など、それまでのすべての実装で置き換わっています。

- toplink.jar

- toplink-essentials.jar

7.2.2.4.2 セッション・ファイナライザのデフォルトでの無効化

TopLink 11g (11.1.1) Technology Preview 3では、パフォーマンス向上のため、セッション・ファイナライザが無効になっています。セッション・ファイナライザを有効にするには、SessionメソッドのsetIsFinalizersEnabled(true)を使用します。

7.2.2.4.3 戻し型VectorおよびHashtableのListまたはMapへの変更

VectorまたはHashtableを返すすべてのSessionまたはClassDescriptorメソッドは、それぞれListまたはMapを返すよう変更されます。この変更に備えるには、VectorおよびHashtableの戻り型をそれぞれListまたはMapにキャストします。たとえば、Javadocでは、ClassDescriptorメソッドのgetMappingsはjava.util.Vectorですが、戻り値はListにキャストされるようにする必要があります。

List mappings = (List) descriptor.getMappings();

現在、変更されMapを戻すようになっているものは次のとおりです。

- ClassDescriptor.getQueryKeys()

- ClassDescriptor.getProperties()

- DescriptorQueryManager.getQueries()

- EISInteraction.getProperties()

- Session.getProperties()

- Session.getQueries()

- getAttributesToAlwaysInclude()

- getSpecialOperations()

- getValuesToExclude()s

7.2.3 タスク3: パッケージの名前変更

TopLinkには、TopLink 11g,リリース1 (11.1.1)以上で、EclipseLinkのすべてのライブラリが含まれるようになりました。EclipseLinkは、TopLinkのコア機能を提供するもので、現在では、JPA 2.x、JAXBおよびその他の標準に基づく永続性サービスやそれらの標準の拡張をサポートしています。また、TopLinkではTopLinkのネイティブAPIもサポートされ続けています(ただし、oracle.toplink.*パッケージは現在すべてorg.eclipse.persistence.*に名前変更となっています)。

新しいコード・ベースを使用するようアプリケーションを移行するには、コードでパッケージ名を変更する必要があります。TopLinkのインストールには、これらをスムーズに行うパッケージの名前変更ツールが含まれています。これらのツールを、次のすべてに対して使用します。

- プロジェクトのソース・コード

- project.xmlファイル

- persistence.xmlファイル

- sessions.xmlファイル

パッケージの名前変更ツールは、toplink_install_directory\toplink\utils\renameディレクトリにあります。WindowsおよびUNIX/LINUX用のスクリプトが含まれています。

このスクリプトを使用し、パッケージの名前変更ツールを実行するには、次を実行します。

1. toplink_install_directory\toplink\utils\rename ディレクトリで packageRename.cmd (Windows)およびpackageRename.sh (UNIX/LINUX)スクリプトを探します。

2. 次の引数を使用し、packageRename.cmdまたはpackageRename.shを実行します。

- sourceLocation: 名前変更するファイルを含むディレクトリ。

- targetLocation: 名前変更したファイルの宛先ディレクトリ。パッケージの名前変更ツールは、JavaおよびXMLファイルが存在する場合、それをすべてを削除してしまうので、空のディレクトリを指定することをお薦めします。

次に例を示します。

packageRename c:/mySourceLocation c:/myDestinationLocation

パッケージの名前変更ツールでは、名前変更するJavaおよびXMLファイルをディレクトリから再帰的に検索します。各ファイルの名前変更されたバージョンは、宛先の場所の対応するディレクトリに保存されます。

7.2.4 タスク4: XML構成ファイルの変換

パッケージの名前変更ツールでは、TopLinkのXML構成ファイルを変換できますが、ファイルの種類によっては他にも変更を行う必要があります。

7.2.4.1 セッションXML

sessions.xmlファイルは現状のまま、使用を継続できます。上位との互換性を高めるには、sessions.xmlファイルに対して名前変更ツールを実行します。

7.2.4.2 デプロイメントXML

TopLink 10.1.3以上のデプロイメントXMLファイルは、TopLink 11.1.1以上で読取りが可能です。これらのファイルは使用し続けることができますが、上位との互換性をより向上させるには、これらのファイルに対し名前変更ツールを実行し、XML Headerのバージョンの文字列を次と置き換えます。

Eclipse Persistence Services

7.2.4.3 永続性XML

TopLinkを永続性プロバイダとして使用するには、persistence.xmlファイルに対して名前変更ツールを実行する必要があります。名前変更ツールにより、永続性プロバイダがEclipseLinkとなるよう更新され、またTopLinkに固有なネイティブなすべてのプロパティもEclipseLinkの対応するものに更新されます。

7.2.4.4 ORM XML

オブジェクト・リレーショナル(ORM) XML構成ファイル(orm.xml)は、TopLinkには依存しないので、更新の必要はありません。

7.2.5 タスク5: Oracle TopLink Workbenchプロジェクトの変換(オプション)

TopLink 11gリリース1 (11.1.1)より前のリリースでは、Oracle TopLink Workbenchというグラフィカルな編集ツールが識別子の構成とプロジェクトのマッピング用に用意されていました。このツールはOracleでは提供しなくなりましたが、対応するEclipseLink WorkbenchというツールがEclipse Foundationから入手できます。古いTopLink Workbenchのプロジェクトは、EclipseLink Workbenchのプロジェクトに変換出力し、それを現在のOracle TopLinkアプリケーションで使用できます。WorkbenchプロジェクトはOracle JDeveloperにインポートすることも可能です。

注意:

EclipseLink Workbenchは、オープンソースのソフトウェアなので、Oracleではサポートされていません。

Oracle TopLink Workbench (.mwp)プロジェクトをEclipseLink Workbenchプロジェクトに変換するには、次の手順を実行します。

1. (前述の)パッケージの名前変更ツールを使用し、Oracle TopLink Workbenchプロジェクト・ソースを移行します。

2. EclipseLink WorkbenchでOracle TopLink Workbenchのプロジェクトを開きます。

3. EclipseLink Workbenchによってプロジェクトが検出され、現在のWorkbenchのバージョンで保存するか質問するメッセージが表示されます。

4. 「すぐに保存」をクリックして、プロジェクトを保存する新しいディレクトリを選択します。

7.3 その他の参考資料

この章のソリューションが実装されているその他のテクノロジおよびツールの詳細は、次の参考資料を参照してください。

8 HibernateからTopLinkへの移行

この章では、HibernateのJPA注釈およびネイティブな独自のAPIを使用するアプリケーションをEclipseLinkによって提供されているTopLinkのJPA実装を使用するように移行する方法を説明します。この移行では、Hibernateの注釈をEclipseLinkの注釈に移行すること、およびHibernateのネイティブAPIをEclipseLinkのJPAにアプリケーションのコードで変換することを行います。標準のJPA注釈およびAPIは変更されません。

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

- 8.1項「ソリューションの概要」

- 8.2項「主なタスク」

- 8.3項「その他の参考資料」

ユース・ケース

Hibernateを永続性プロバイダとして使用するかわりに、TopLinkを使用するようアプリケーションを移行を行いたいと開発者が考えています。

解決方法

この章の手順に従って、アプリケーションをアップグレードします。

コンポーネント

- TopLink 12cリリース1 (12.1.2)以上。

注意:

TopLinkのコア機能は、オープン・ソースのEclipse Foundationの永続性フレームワークであるEclipseLinkによって提供されています。EclipseLinkでは、Java Persistence API (JPA)、Java Architecture for XML Binding (JAXB)、および標準に基づいたその他の永続性テクノロジと、それらの標準の拡張が実装されます。TopLinkには、EclipseLinkのすべてに加え、Oracleの追加機能が含まれています。

8.1 ソリューションの概要

Hibernateは、Java環境のためのオブジェクト・リレーショナル・マッピング(ORM)ツールです。これは、Javaオブジェクトをリレーショナル・データベース・アーティファクトにマッピングしたり、Javaのデータ型をSQLのデータ型にマッピングしたりするためのフレームワークを提供します。また、データベースに問い合せて、データを取得することもできます。

Hibernateの詳細は、http://www.hibernate.orgを参照してください。

移行の理由

HibernateからTopLinkに移行する理由には、次のようなものがあります。

- パフォーマンスとスケーラビリティ: EclipseLinkのキャッシング・アーキテクチャでは、オブジェクトの作成を最小限に抑えて、インスタンスを共有できます。EclipseLinkのキャッシングでは、シングルノードおよびクラスタ化されたデプロイメントがサポートされています。

- 主要なリレーショナル・データベースのサポート: EclipseLinkでは、すべての主要なリレーショナル・データベースとそれに固有な拡張を継続的にサポートします。EclipseLinkはOracle Databaseに対する最高のORMソリューションでもあります。

- 包括的な永続性ソリューション: EclipseLinkには、業界をリードするオブジェクトリレーショナル・サポートが用意されていますが、さらにコア・マッピング機能も使用して、Object-XML (JAXB)、サービス・データ・オブジェクト(SDO)およびデータベースWebサービス(DBWS)が提供されています。要件に応じて、同じコア永続性エンジンに基づく永続性サービスを複数使用することもできます。

- JPAのサポート: EclipseLinkは、JPA 2.0の参照実装で、JPAの今後のバージョンをサポートします。

8.2 主なタスク

Hibernateを永続性プロバイダとして使用するアプリケーションでTopLinkに移行するには、次のタスクを実行します。

- タスク1: Hibernateのエンティティ注釈の変換

- タスク2: Hibernateのカスタム・シーケンス・ジェネレータ注釈の変換

- タスク3: Hibernateのマッピング注釈の変換

- タスク4: persistence.xmlファイルの変更

- タスク5: Hibernate APIからEclipseLink APIへの変換

8.2.1 タスク1: 前提条件

TopLink 12cリリース1 (12.1.2)以上。

http://www.oracle.com/technetwork/middleware/toplink/downloads/index.htmlからTopLinkをダウンロードします。

8.2.2 タスク1: Hibernateのエンティティ注釈の変換

org.hibernate.annotations.Entityクラスで定義されているHibernateのエンティティ注釈には、JPAの標準@Entity注釈で定義されている内容を超えるメタデータが追加されています。

例8-1に、Hibernateのエンティティ注釈のサンプルを示します。この例では、selectBeforeUpdate、dynamicInsert、dynamicUpdate、optimisticLockおよびpolymophism属性が使用されています。Hibernateのエンティティ注釈には、この例には示されていないmutableおよびpersister属性も定義されています。

例8-1 Hibernateのエンティティ注釈のサンプル

@org.hibernate.annotations.Entity(
selectBeforeUpdate = true,
dynamicInsert = true,
dynamicUpdate = true,
optimisticLock = OptimisticLockType.ALL,
polymorphism = PolymorphismType.EXPLICIT)

次の項では、選択、ロック、多相性、動的更新および挿入をEclipseLinkが処理する方法を説明します。詳細は、Eclipselinkのドキュメントの「EclipseLink/Examples/JPA/Migration/Hibernate/V3Annotations」を参照してください。

http://wiki.eclipse.org/EclipseLink/Examples/JPA/Migration/Hibernate/V3Annotations

8.2.2.1 SelectBeforeUpdate、dynamicInsertおよびdynamicUpdate属性の変換

HibernateでselectBeforeUpdate属性を指定すると、オブジェクトが実際に変更されたことが確実な場合以外、HibernateはSQL UPDATEを実行しません。dynamicInsert属性を指定すると、INSERT SQL文が実行時に生成されて、null以外の値の列のみがストアされます。dynamicUpdate属性を指定すると、UPDATE SQL文が実行時に生成されて、値が変更された列のみをストアできます。

EclipseLinkのデフォルトでは、マップされたすべての列が常に挿入され、変更された列のみが更新されます。代替操作が必要な場合は、Javaコード、SQLまたはストアド・プロシージャを使用して、これらの操作に使用される問合せをカスタマイズできます。

8.2.2.2 OptimisticLock属性の変換

Hibernateでは、optimisticLock属性によって、オプティミスティック・ロックの戦略が決まります。

EclipseLinkのオプティミスティック・ロック機能では、Hibernateのすべてのロック・タイプに加えて他のタイプもサポートされています。表8-1に、Hibernateの@Entity(optimisticLock)属性に対応するEclipseLinkのロッキング・ポリシーを示します。これらのポリシーは、EclipseLinkの@OptimisticLocking注釈またはEclipseLinkのorm.xmlファイルのどちらかで構成できます。詳細は、@OptimisticLockingを参照してください。

表8-1 Hibernateのオプティミスティック・ロックからEclipseLinkのオプティミスティック・ロックへの変換

HibernateのOptimisticLockタイプ

説明

EclipseLinkのOptimisticLocking

NONE

オプティミスティック・ロックなし

EclipseLinkはデフォルトでオプティミスティック・ロックなしになります。

VERSION

列バージョンを使用

JPA @Version注釈またはEclipseLinkの次の注釈を使用します。

@OptimisticLocking(type = OptimisticLockingType.VERSION_COLUMN)

DIRTY

変更された列を比較

JPA @Version注釈またはEclipseLinkの次の注釈を使用します。

@OptimisticLocking(type = OptimisticLockingType.CHANGED_COLUMNS)

ALL

すべての列を比較

EclipseLinkの次の注釈が使用されます

@OptimisticLocking(type = OptimisticLockingType.ALL_COLUMNS)

さらに、EclipseLinkでは、OptimisticLockingType.SELECTED_COLUMNS注釈を使用して、選択した列の特定のセットも比較できます。これにより、CHANGEDまたはALLの戦略がニーズに合わない場合に、比較する必要がある重要な列を選択できます。

8.2.3 タスク2: Hibernateのカスタム・シーケンス・ジェネレータ注釈の変換

Hibernateでは、@GeneratedValue注釈によって、ID生成戦略を定義します。@GenericGeneratorでは、Hibernate固有のIDジェネレータを定義できます。例8-2は、シーケンス値のカスタム・ジェネレータを示しています。

例8-2 シーケンス値のカスタム・ジェネレータ

.
.
.
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "mypackage.UUIDGenerator")
public String getTransactionGuid()
.
.
.

EclipseLinkでは、@GeneratedValue注釈を使用して、カスタム・シーケンス・ジェネレータを実装および登録できます。詳細は、次のEclipseLinkのドキュメントのカスタム・シーケンスの使用方法に関する項を参照してください。

http://wiki.eclipse.org/EclipseLink/Examples/JPA/CustomSequencing

8.2.4 タスク3: Hibernateのマッピング注釈の変換

次の項では、Hibernateの様々な注釈をEclipseLinkの注釈に変換する方法を説明します。

8.2.4.1 @ForeignKey注釈の変換

Hibernateの@ForeignKey注釈では、スキーマ生成時に使用する外部キーの名前を定義できます。

EclipseLinkでは、外部キーに妥当な名前を生成し、使用する名前を指定するための注釈やeclipselink-orm.xmlはサポートしていません。移行時には、EclipseLinkでスキーマ(DDL)コマンドをデータベースに直接生成するのではなく、スクリプト・ファイルに生成することをお薦めします。そうすれば、実行する前に、別の名前を使用するようにスクリプトをカスタマイズできます。

注意:

外部キー名はEclipseLinkでは実行時に使用されませんが、EclipseLinkがスキーマを削除しようとする場合には必要です。この場合、削除スクリプトをファイルに生成して、作成時に使用された外部キー名と一致するようにカスタマイズする必要があります。

8.2.4.2 @Cache注釈の変換

Hibernateでは、@Cache注釈によって、エンティティおよびリレーションシップのキャッシングを構成します。EclipseLinkでは、データ・キャッシュではなくエンティティ・キャッシュが使用されるので、リレーションシップは自動的にキャッシュされます。これらの場合、@Cache注釈を移行時に削除する必要があります。@Cache注釈がエンティティに使用されている場合は、EclipseLinkの@Cache注釈と同様の動作になります。@Cache注釈および同等のeclipselink-orm.xml構成値の詳細は、『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』を参照してください。

8.2.5 タスク4: persistence.xmlファイルの変更

persistence.xmlファイルは、JPA永続性のデプロイメント・ディスクリプタ・ファイルです。ここには、永続性ユニットを指定し、管理対象永続性クラス、オブジェクト・リレーショナル・マッピング、およびデータベース接続の詳細を宣言します。例8-3に、Hibernateを使用するアプリケーションのpersistence.xmlファイルを示します。Hibernateに固有の値は、太字のフォントで示します。

例8-3 Hibernateを使用するアプリケーションの永続性ファイル

<persistence>
<persistence-unit name="helloworld">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/DefaultDS</jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
</properties>
</persistence-unit>
</persistence>

8.2.5.1 変更されたpersistence.xmlファイル

例8-4に、EclipseLinkを使用するアプリケーション用に変更されたpersistence.xmlファイルを示します。主な相違は、永続性プロバイダの値などです。EclipseLinkの場合は、この値は、org.eclipse.persistence.jpa.PersistenceProviderです。EclipseLink固有のプロパティ名には、通常、eclipselink.target-databaseのようにeclipselinkという接頭辞が付きます。EclipseLinkに固有の値は、太字のフォントで示します。

例8-4 EclipseLink用に変更された永続性ファイル

<xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="helloworld">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>java:/DefaultDS</jta-data-source>
<!-- For Java SE applications, entity classes must be specified for EclipseLink weaving. For Java EE applications, the classes are found automatically. -->
<class>Todo</class>
<properties>
<property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
<property name="eclipselink.ddl-generation.output-mode" value="database"/>
<property name="eclipselink.logging.level" value="FINE"/>
</properties>
</persistence-unit>
</persistence>

8.2.5.2 データベース表の削除および作成

本番環境では、通常はデータベースにスキーマが設定されています。永続性ユニットに定義されている次のプロパティは、例およびデモ用に適しています。これらのプロパティを指定すると、EclipseLinkでデータベース表が自動的に削除および作成されます。以前に存在した表は削除されます。

データベース表の削除および作成機能を使用するには、次のプロパティをpersistence.xmlファイルに追加します。

<property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
<property name="eclipselink.ddl-generation.output-mode" value="database"/>

この機能の詳細は、『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』のddl-generationに関する項のdrop-and-create-tablesのエントリを参照してください。

8.2.5.3 データベース表の作成または拡張

データベース表の作成または拡張機能では、新しいデータベース表を作成したり、既存の表を変更することによって、データベース・スキーマとオブジェクト・モデルを一致させることができます。フィールド名の変更を指定したり、フィールドを追加および削除することによって、既存の表を変更できます。

注意:

現在のリリースでは、データベース表の作成または拡張機能では、既存の列を名前変更したり削除できません。欠落している表の列のみを追加できます。

データベース表の作成または拡張機能では、テスト・データを再移入する必要を減らせます。オブジェクト・モデルの変更により、スキーマの変更時に、データベース表の削除および作成機能の使用を回避できます。また、データベース表の作成または拡張機能では、表の列を追加する拡張も使用できます。

データベース表の作成または拡張機能を使用するには、次のプロパティをpersistence.xmlファイルに追加します。コンテキストがロードされたら、永続性ユニットで必要とされる各表のデータベースに対し、EclipseLinkが問合せを行い、その結果を使用して表を作成または拡張する必要があるか判断されます。

<property name="eclipselink.ddl-generation" value="create-or-extend-tables" />
<property name="eclipselink.ddl-generation.output-mode" value="database" />

この機能の詳細は、『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』のddl-generationに関する項のcreate-or-extend-tablesのエントリを参照してください。

8.2.6 タスク5: Hibernate APIからEclipseLink APIへの変換

表8-2で、JPAプロジェクトでよく使用されるHibernateクラスおよび同等のEclipseLink (JPA)インタフェースを説明します。Hibernateのすべてのクラスはorg.hibernateパッケージにあります。すべてのJPAインタフェース(およびPersistenceクラス)はjavax.persistenceパッケージにあります。

EclipseLinkのAPI の詳細は、『Oracle TopLink Java APIリファレンス』を参照してください。

表8-2 Hibernateのクラスおよび同等のJPAインタフェース

org.hibernate

javax.persistence

説明

cfg.Configuration

Persistence

セッション・ファクトリ(Hibernate内)またはエンティティ・マネージャ・ファクトリ(JPA内)を構成するブートストラップ・クラスを提供します。通常、これはJVM用の単一のセッション(またはエンティティ・マネージャ)ファクトリを作成するために使用します。

SessionFactory

EntityManagerFactory

Hibernateセッション(またはJPAエンティティ・マネージャ)をオープンして、ユーザー・リクエストを処理するためのAPIを提供します。一般に、セッション(またはエンティティ・マネージャ)は、クライアント・リクエストを処理するスレッドごとにオープンされます。

Session

EntityManager

エンティティをデータベースにストアまたはデータベースからロードするためのAPIを提供します。トランザクションを取得して問合せを作成するためのAPIも提供します。

Transaction

EntityTransaction

トランザクションを管理するためのAPIを提供します。

Query

Query

問合せを実行するためのAPIを提供します。

8.3 その他の参考資料

この章のソリューションが実装されているその他のテクノロジおよびツールの詳細は、次の参考資料を参照してください。

- http://www.hibernate.orgのHibernate。

- EclipseLinkのドキュメント(http://wiki.eclipse.org/EclipseLink/Examples/JPA/Migration/Hibernate)の「EclipseLink/Examples/JPA/Migration/Hibernate」。

9 コンポジット永続性ユニットによる複数データベースの使用

Oracle TopLinkでは、コンポジット永続性ユニットを使用して、(エンティティ・タイプの独自のセットがそれぞれに設定された)複数の永続性ユニットを単一の永続性コンテキストとして公開できます。コンポジット永続性ユニットの一部である個々の永続性ユニットを、コンポジット・メンバー永続性ユニットと呼びます。

注意:

TopLinkは、パーティショニングを通じて複数のデータベースをサポートしています。第10章「クラスタ内のアプリケーションのスケーリング」を参照してください。

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

- 9.1項「ソリューションの概要」

- 9.2項「ソリューションの実装」

- 9.3項「その他の参考資料」

ユース・ケース

ユーザーが、複数の永続性ユニットをアプリケーション内で1つの永続性コンテキストとして公開する必要があります。

解決方法

TopLinkでは、複数のメンバーの永続性ユニットを含むコンポジット永続性ユニットをサポートできます。

コンポーネント

- TopLink 12cリリース1 (12.1.2)以上。

注意:

TopLinkのコア機能は、オープン・ソースのEclipse Foundationの永続性フレームワークであるEclipseLinkによって提供されています。EclipseLinkでは、Java Persistence API (JPA)、Java Architecture for XML Binding (JAXB)、および標準に基づいたその他の永続性テクノロジと、それらの標準の拡張が実装されます。TopLinkには、EclipseLinkのすべてに加え、Oracleの追加機能が含まれています。

- 複数のデータベース。

例

関連情報は、次のEclipseLinkの例を参照してください。

- http://wiki.eclipse.org/EclipseLink/Examples/JPA/Composite

9.1 ソリューションの概要

コンポジット永続性ユニットでは、次のことを行えます。

- 複数の永続性ユニット内の任意のエンティティ間のリレーションシップのマッピング

- 複数のデータベースおよび様々なデータ・ソースにストアされているエンティティへのアクセス

- エンティティの完全なセット全体に対する問合せおよびトランザクションの容易な実行

例9-1は、1つの永続性コンテキストから2つの異なるデータベースにデータを永続化する方法を示しています。

例9-1 複数のデータベースの使用

em.persist(new A(..));
em.persist(new B(..));
// You can insert A into database1 and insert B into database2.
// The two databases can be from different vendors.

em.flush();

図9-1は、単純なコンポジット永続性ユニットを示しています。EclipseLinkではpersistence.xmlファイルを処理し、2つのコンポジット・メンバー永続性ユニットを含むコンポジット永続性ユニットを検出します。

- クラスAは、member1.jarファイルにあるmemberPu1という名前の永続性ユニットによってマップされています。

- クラスBは、member2.jarファイルにあるmemberPu2という名前の永続性ユニットによってマップされています。

図9-1 単純なコンポジット永続性ユニット

9.1.1 コンポジット永続性ユニットの要件

コンポジット永続性ユニットを使用する際には、次の要件に注意してください。

- 各コンポジット・メンバー永続性ユニットの名前は、コンポジット内で一意である必要があります。

- 永続性ユニット全体に対応するtransaction-typeおよび他のプロパティ(ターゲット・サーバー、ロギング・トランザクションなど)はコンポジット永続性ユニットで定義してください。そうでない場合、コンポジット・メンバーに定義されたトランザクション・タイプ、ターゲット・サーバー情報、ロギング・プロパティは無視されます。

9.2 ソリューションの実装

この項には、次の項目が含まれます。

- タスク1: コンポジット永続性ユニットの構成

- タスク2: コンポジット永続性ユニットの使用

- タスク3: コンポジット永続性ユニットのデプロイ

9.2.1 タスク1: コンポジット永続性ユニットの構成

コンポジット永続性ユニットは通常の永続性要素なので、persistence.xmlファイルが必要です。例9-2に、persistence.xmlのサンプル・ファイルを示します。datasourceまたはjdbcプロパティがないことを確認してください。

例9-2 コンポジット永続性ユニットのpersistence.xmlファイル

<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence persistence_1_0.xsd" version="1.0">
<persistence-unit name="compositePu" transaction-type="JTA">
<provider>
org.eclipse.persistence.jpa.PersistenceProvider
</provider>

<jar-file>member1.jar</jar-file>
<jar-file>member2.jar</jar-file>
<properties>
<property name="eclipselink.composite-unit" value="true"/>
<property name="eclipselink.target-server" value="WebLogic_10"/>
</properties>
</persistence-unit>
</persistence>

オプションで、<property name="eclipselink.composite-unit" value="true"/>プロパティを使用して、永続性ユニットをコンポジット永続性ユニットとして指定できます。

<jar-file>要素を使用して、コンポジット・メンバー永続性ユニットを含むJARファイルを指定します。コンポジット永続性ユニットには、指定したJARファイルであるすべてのコンポジット・メンバー永続性ユニットが含まれます。

9.2.2 タスク2: コンポジット永続性ユニットの使用

コンポジット永続性ユニットは他の永続性ユニットと同様に使用できます(次に示すとおり、EntityManagerを注入されます)。

@PersistenceContext(unitName="compositePu")
EntityManagerFactory entityManagerFactory;

@PersistenceContext(unitName="compositePu")
EntityManager entityManager;

また、手動で作成することもできます。

EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("compositePu", properties);

9.2.3 タスク3: コンポジット永続性ユニットのデプロイ

複数の永続性ユニットをデプロイするには、同じクラス・ローダーにすべてのJARファイル(コンポジット永続性ユニットおよびそのメンバー)をデプロイします。

- Oracle WebLogic Serverにデプロイする場合は、JARファイルをEARファイルまたは、WARファイルのWEB-INF/libフォルダにパッケージします。

- スタンドアロン・アプリケーションとして実行している場合、クラス・パスにJARファイルを追加します。

重要な要件については、第9.1.1章「コンポジット永続性ユニットの要件」を参照してください。

9.3 その他の参考資料

この章のソリューションが実装されているその他のテクノロジおよびツールの詳細は、次の参考資料を参照してください。

コンポジット永続性ユニットに関するその他の情報は、『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』の@CompositeMember、composite.unit、composite-unit.memberに関する項を参照してください。

- コンポジット永続性ユニットの制限

- 依存関係が含まれるコンポジット・メンバー永続性ユニットの構成

- コンポジット永続性ユニットおよびコンポジット・メンバー永続性ユニットで使用されるすべての永続性ユニット・プロパティ

- コンポジット永続性ユニットEntityManagerFactoryを作成中に、Persistence.createEntityManagerFactoryメソッドでコンポジット・メンバー永続性ユニットに永続性ユニット・プロパティを渡す方法

- コンポジット永続性ユニットおよびコンポジット・メンバー永続性ユニットで使用されるすべてのエンティティ・マネージャ

- コンポジット永続性ユニットEntityManagerFactoryのemf.createEntityManagerメソッドでコンポジット・メンバー永続性ユニットにエンティティ・マネージャ・プロパティを渡す方法

9.3.1 関連Javadoc

詳細は、『Oracle TopLink Java APIリファレンス』で次のAPIを参照してください。

- PersistenceUnitPropertiesクラス

- Persistence.createEntityMangerクラス

- EntityManagerFactoryインタフェース

10 クラスタ内のアプリケーションのスケーリング

この章では、アプリケーション・サーバー環境でスケーラビリティを保証するためにOracle TopLinkアプリケーションを構成する手順を説明します。この手順は、すべてのアプリケーション・サーバー・クラスタに適用できる汎用的なものですが、Oracle WebLogic ServerおよびOracle GlassFish Serverに対応した追加のコンテンツも用意されています。必要に応じて、ベンダーのドキュメントを参照してください。

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

- 10.1項「ソリューションの概要」

- 10.2項「ソリューションの実装」

- 10.3項「その他の参考資料」

ユース・ケース

顧客の要求に応えるためにアプリケーションを拡張する必要があります。

解決方法

この実装は、キャッシュの構成、キャッシュ・コーディネーションの構成、データのパーティション化を使用して実現できます。

コンポーネント

- TopLink 12cリリース1 (12.1.2)以上。

注意:

TopLinkのコア機能は、オープン・ソースのEclipse Foundationの永続性フレームワークであるEclipseLinkによって提供されています。EclipseLinkでは、Java Persistence API (JPA)、Java Architecture for XML Binding (JAXB)、および標準に基づいたその他の永続性テクノロジと、それらの標準の拡張が実装されます。TopLinkには、EclipseLinkのすべてに加え、Oracleの追加機能が含まれています。

- クラスタをサポートするアプリケーション・サーバー。

- 対応するすべてのJDBCデータベース。

例

サンプルへのリンクは、10.3項「その他の参考資料」を参照してください。

10.1 ソリューションの概要

アプリケーション・サーバー・クラスタにデプロイされたEclipseLinkアプリケーションは、クラスタのスケーラビリティ、負荷分散およびフェイルオーバーのメリットを受けることができます。これらの機能は、EclipseLinkアプリケーションの可用性を高め、アプリケーションの需要拡大に伴ってスケーリングできます。EclipseLinkのアプリケーションは、アプリケーション・サーバー・クラスタへも、スタンドアロンのサーバー環境と同様にデプロイできます。ただし、アプリケーション・サーバー・クラスタの場合には、キャッシュの一貫性を確保するために、その他に計画や構成を実行する必要があります。

EclipseLinkでは、オブジェクトおよびそのリレーションシップのデータベース・アクセスを回避する共有(L2)オブジェクト・キャッシュが利用されます。このキャッシュはデフォルトで有効になり、アプリケーションのパフォーマンスが向上します。アプリケーション・サーバー・クラスタでキャッシングを使用すると、1つのサーバーで行われた変更が、他のサーバーでキャッシュされているオブジェクトに反映されないために、整合性の問題(失効データなど)が発生する場合があります。キャッシュの整合性が問題になるのは、頻繁に更新されるオブジェクトのみです。読取り専用のオブジェクトは、キャッシュの整合性の影響を受けません。キャッシュの詳細は、次を参照してください。

http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Caching/Caching_Overview

キャッシュの整合性に対処するには、次のように様々な方法があります。

- キャッシュ・コーディネーションを使用します。キャッシュ・コーディネーションは、クラスタ内のサーバー間で変更をブロードキャストして、変更されたオブジェクトの更新または無効化を行う機能です。

- 分散キャッシングを使用します。TopLink Gridとは、TopLinkとOracle Coherenceを統合した、分散環境で運用した場合に発生するキャッシュの整合性の問題の多くに対処するものです。TopLink Gridの詳細は、第19章「TopLink GridでのOracle Coherenceを使用したアプリケーションのスケーリング」を参照してください。

- オプティミスティック・ロックを使用します。オプティミスティック・ロックは、無効なオブジェクトへの更新を防ぎ、キャッシュ内でオブジェクトが無効化されるようにトリガーする機能です。

- キャッシュをリフレッシュします。キャッシュを更新すると、キャッシュに最新のデータがロードされます。

- 非常に不安定なエンティティでは共有キャッシュを無効にするか、キャッシュを読取り専用オブジェクトに制限します。

10.2 ソリューションの実装

次のタスクでは、EclipseLinkアプリケーションをアプリケーション・サーバー・クラスタでスケーリングするための一般的な手順を説明します。タスクは、アプリケーションのデプロイ前に完了する必要があります。

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

- タスク1: キャッシュの整合性の構成

- タスク2: EclipseLinkの有効化の確認

- タスク3: すべてのアプリケーション・サーバーがクラスタ内にあることの確認

- データのスケールのためのデータ・パーティション化の使用

10.2.1 タスク1: キャッシュの整合性の構成

このタスクには、アプリケーション・サーバーのクラスタにアプリケーションがデプロイされた場合に、アプリケーションが失効データを使用する可能性を少なくする様々な構成オプションが含まれています。キャッシュ・コーディネーション・オプションは、クラスタ化されたアプリケーション用に特に設計されていますが、すべてのオプションを評価し、(適用可能な場合は)一緒に使用して、アプリケーションのパフォーマンスが最高になるようなソリューションを作成します。キャッシュを適切に構成すれば、キャッシュ・コーディネーションを使用する必要がなくなる場合もあります。これらのオプションの詳細は、次を参照してください。

http://wiki.eclipse.org/Introduction_to_Cache_%28ELUG%29#Handling_Stale_Data

次の構成オプションを利用できます。

- エンティティのキャッシュの無効化

- キャッシュのリフレッシュ

- エンティティのキャッシュの期限の設定

- オプティミスティック・ロックの設定

- キャッシュ・コーディネーションの使用

注意:

TopLinkでCoherenceをL2キャッシュとして使用できるようにするTopLinkとCoherenceの統合が提供されています。TopLink Gridの詳細は、第19章「TopLink GridでのOracle Coherenceを使用したアプリケーションのスケーリング」を参照してください。

10.2.1.1 エンティティのキャッシュの無効化

非常に不安定なエンティティまたは必要に応じてすべてのエンティティで共有キャッシュを無効にします。すべてのオブジェクトの共有キャッシュを無効にするには、persistence.xmlファイルの<shared-cache-mode>要素を使用します。次に例を示します。

<shared-cache-mode>NONE</shared-cache-mode>

デフォルトでは、DISABLE_SELECTIVEが構成されており、エンティティごとにキャッシュを無効にできます。共有キャッシュを選択的に有効または無効にするには、エンティティを定義する際に、@Cache注釈のshared属性を使用します。次に例を示します。

@Entity
@Cache(shared=false)
public class Employee {
}

10.2.1.2 キャッシュのリフレッシュ

アプリケーションが現在のデータの使用を確実にするために、キャッシュをリフレッシュするとデータベースからキャッシュがリロードされます。キャッシュは様々な方法でリフレッシュできます。

@Cache注釈には、データベースに対するすべての問合せで強制的にキャッシュをリフレッシュさせるalwaysRefresh属性とrefreshOnlyIfNewer属性が用意されています。キャッシュは、データベース内のオプティミスティック・ロック値がキャッシュ内のものよりも実際に新しい場合にのみリフレッシュされます。

@Entity
@Cache(
alwaysRefresh=true,
refreshOnlyIfNewer=true)
public class Employee {
}

javax.persistence.Cacheインタフェースには、キャッシュが最新でない場合に失効オブジェクトを削除するメソッドが含まれています。

- evictAllメソッドは、キャッシュ内のすべてのオブジェクトを無効にします。

em.getEntityManagerFactory().getCache().evictAll();

- evictメソッドは、特定のクラスを無効にします。

em.getEntityManagerFactory().getCache().evict(MyClass);

これまでに説明したメソッドは受動的で、次回にキャッシュにアクセスしたときにのみオブジェクトがリフレッシュされます。オブジェクトを能動的にリフレッシュするには、EntityManager.refreshメソッドを使用します。このメソッドは1回に1つのオブジェクトをリフレッシュします。

キャッシュをリフレッシュする問合せをトリガーする、問合せのヒントを設定するsetHintメソッドを設定することも可能です。次に例を示します。

Query query = em.createQuery("Select e from Employee e");
query.setHint("javax.persistence.cache.storeMode", "REFRESH");

最後にネイティブAPIのメソッドも使用できます。詳細は、『Oracle TopLink Java APIリファレンス』のClassDescriptorに関する項を参照してください。

10.2.1.3 エンティティのキャッシュの期限の設定

キャッシュ有効期限を設定した場合、指定時間が経過すると、キャッシュされたオブジェクト・インスタンスが無効になります。そのオブジェクトを使用しようとすると、最新バージョンのオブジェクトがデータ・ソースからリロードされます。有効期限は、アプリケーションが確実に最新データを使用するようにするのに便利です。有効期限を設定するには、様々な方法があります。

@Cache注釈には、特定の時間が経つとキャッシュ・インスタンスを削除するexpiryおよびexpiryTimeOfDay属性が用意されています。expiry属性は、ミリ秒単位で入力します。値を指定しない場合のデフォルト値は-1で、有効期限が無効になっていることを示します。expiryTimeOfDay属性は、org.eclipse.persistence.annotations.TimeOfDayインタフェースのインスタンスです。次の例では、5分後にオブジェクトが期限切れになるように設定しています。

@Entity
@Cache(expiry=300000)
public class Employee {
}

10.2.1.4 オプティミスティック・ロックの設定

オプティミスティック・ロックでは、あるユーザーが別のユーザーの作業を上書きできないようにします。ロックは、複数のサーバーまたは複数のアプリケーションが同じデータにアクセスする場合に重要で、単一サーバーとマルチサーバーの両方の環境に関係があります。マルチサーバー環境においては、アプリケーションがキャッシュ・リフレッシュやキャッシュ・コーディネーションを使用している場合であっても、やはりロックは必要です。オプティミスティック・ロックを設定するには、様々な方法があります。

標準のJPA @Versionの注釈は、単一値の値およびタイムスタンプ・ベースのロックで使用されます。ただし、高度なロッキング機能には、@OptimisticLocking注釈を使用します。@OptimisticLocking注釈には、エンティティを更新または削除する際に使用するオプティミスティック・ロックのタイプを指定します。オプティミスティック・ロックは、@Entityまたは@MappedSuperclass注釈でサポートされています。次のポリシーをtype属性内に設定して利用できます。

- ALL_COLUMNS: このポリシーでは、更新または削除操作を実行するときに、WHERE句で表のすべてのフィールドを比較します。

- CHANGED_COLUMNS: このポリシーでは、更新操作の実行時に、WHERE句で変更されたフィールドのみを比較します。削除操作では、主キーのみが比較されます。

- SELECTED_COLUMNS: このポリシーでは、更新または削除操作を実行するときに、WHERE句で選択したフィールドを比較します。指定したフィールドはマップされている必要があり、主キーではない必要があります。

- VERSION_COLUMN: (デフォルト)このポリシーでは、単一のバージョン番号をオプティミスティック・ロックに使用することを許可します。バージョン・フィールドはマップされている必要があり、主キーではない必要があります。親オブジェクトが私有する子オブジェクトのバージョン・フィールドが変更された場合に、その親オブジェクトのバージョン・フィールドが強制的に自動更新されるようにするには、cascadedメソッドをtrueに設定します。デフォルトでは、このメソッドはfalseに設定されます。

10.2.1.5 キャッシュ・コーディネーションの使用

キャッシュ・コーディネーションは、分散セッション間で変更を同期します。すべてのアプリケーションでデータの整合性を維持するのが困難なアプリケーション・サーバー・クラスタでは、キャッシュ・コーディネーションが最も有効です。さらに、1つの環境内のサーバー数が増えるにつれて、キャッシュの整合性を保つのはますます難しくなります。

キャッシュ・コーディネーションは、クラスタ内のセッション(EntityManagerFactoryまたは永続性ユニット)間のトランザクション・オブジェクトの変更通知をブロードキャストすることにより動作します。アプリケーションが読取り中心で、複数の分散セッションで運用される同一アプリケーションによって変更が実行される場合に、キャッシュ・コーディネーションは最も有効です。

キャッシュ・コーディネーションを使用すると、失効データが大幅に減少しますが、遅延のために失効データが発生する可能性を完全になくすことはできません。さらに、キャッシュ・コーディネーションにより、分散アーキテクチャで発生するオプティミスティック・ロック例外の数は減少し、アプリケーションで失敗するトランザクションや繰り返されるトランザクションの数も減少します。とはいえ、キャッシュ・コーディネーションを行っても、効果的なロック・ポリシーが不要になることはありません。現在のデータを確実に使用するには、オプティミスティック・ロックまたはペシミスティック・ロックとともにキャッシュ・コーディネーションを使用しますが、オプティミスティック・ロックの使用の方をお薦めします。

キャッシュ・コーディネーションはRemote Method Invocation (RMI)およびJava Message Service (JMS)プロトコル上でサポートされており、persistence.xmlファイルの永続性プロパティを使用して宣言的に構成することも、キャッシュ・コーディネーションのAPIを使用して構成することもできます。永続性プロパティに一致するシステム・プロパティも使用できます。

キャッシュ・コーディネーションの詳細は、次を参照してください。

『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』

10.2.1.5.1 キャッシュ同期の設定

キャッシュ同期では、オブジェクトの変更通知がセッション・メンバー間にブロードキャストされる方法を決定します。使用できる同期オプションは次のとおりです。

- SEND_OBJECT_CHANGES: (デフォルト)このオプションでは、変更に関するデータを含む、変更されたオブジェクトのリストがブロードキャストされます。このデータは、受信キャッシュにマージされます。

- INVALIDATE_CHANGED_OBJECTS: このオプションでは、変更されたオブジェクトのIDリストがブロードキャストされます。受信キャッシュでは、データを変更するのではなく、オブジェクトが無効にされます。このオプションは、他のクラスタ・メンバーに対しデータを送信したり処理を実行するには最も軽量です。

- SEND_NEW_OBJECTS_WITH_CHANGES: このオプションは、トランザクションで新規作成されたオブジェクトも含まれる点以外はSEND_OBJECT_CHANGESオプションと同じです。

- NONE: このオプションでは、キャッシュ・コーディネーションは行われません。

@cache注釈のcoordinationType属性は、同期を指定するために使用します。次に例を示します。

@Entity
@Cache(CacheCoordinationType.SEND_NEW_OBJECTS_CHANGES)
public class Employee {
}

ClassDescriptor.setCacheSynchronizationTypeネイティブAPIメソッドも、同期を指定するために使用できます。詳細は、『Oracle TopLink Java APIリファレンス』のClassDescriptorに関する項を参照してください。

10.2.1.5.2 永続性プロパティを使用したJMSキャッシュ・コーディネーションの構成

次の例は、persistence.xmlファイルでキャッシュ・コーディネーションを構成する方法を示しており、通知のブロードキャストにJMSを使用しています。JMSでは、JMSトピック、JNDI名およびトピック接続ファクトリのJNDI名を指定します。JMSトピックでは、JTAを有効にせず、永続性メッセージを指定しないでください。

<property name="eclipselink.cache.coordination.protocol" value="jms" />
<property name="eclipselink.cache.coordination.jms.topic"
value="jms/EmployeeTopic" />
<property name="eclipselink.cache.coordination.jms.factory"
value="jms/EmployeeTopicConnectionFactory" />

クラスタで実行されるアプリケーションでは、リソースを探して使用するにはトピックで十分なので、URLは通常不要です。クラスタ外部で実行されるアプリケーションの場合は、URLが必要です。WebLogicサーバー・クラスタのURLの例を次に示します。

<property name="eclipselink.cache.coordination.jms.host"
value="t3://myserver:7001/" />

必要な場合は、サーバーにアクセスするために必要なユーザー名とパスワードも設定できます。次に例を示します。

<property name="eclipselink.cache.coordination.jndi.user" value="user" />
<property name="eclipselink.cache.coordination.jndi.password" value="password" />

10.2.1.5.3 永続性プロパティを使用したRMIキャッシュ・コーディネーションの構成

次の例は、persistence.xmlファイルでキャッシュ・コーディネーションを構成する方法を示し、通知のブロードキャストにRMIを使用しています。

<property name="eclipselink.cache.coordination.protocol" value="rmi" />

クラスタで実行されるアプリケーションでは、JNDIがレプリケートされてサーバーが相互を参照できるので、URLは通常不要です。アプリケーションがクラスタ外部で実行される場合またはJNDIがレプリケートされない場合は、各サーバーでURLを指定する必要があります。これは、persistence.xmlファイルを使用して行えますが、各サーバーに対して別のpersistence.xmlファイル(たとえばJARまたはEAR)が必要になり、通常は望ましくありません。2番目のオプションとしては、キャッシュ・コーディネーションAPIを使用して、URLをプログラムで設定します。詳細は、「キャッシュ・コーディネーションAPIを使用したキャッシュ・コーディネーションの構成」を参照してください。最後のオプションは、各アプリケーション・サーバーのシステム・プロパティとしてURLを設定する方法です。次の例では、システム・プロパティを使用してWebLogicサーバー・クラスタのURLを設定しています。

-Declipselink.cache.coordination.jms.host=t3://myserver:7001/

必要な場合は、サーバーにアクセスするために必要なユーザー名とパスワードも、次のように設定できます。

<property name="eclipselink.cache.coordination.jndi.user" value="user" /><property name="eclipselink.cache.coordination.jndi.password" value="password" />

RMIキャッシュ・コーディネーションでは、非同期または同期のブロードキャスト通知を使用できます(デフォルトでは非同期です)。同期ブロードキャストでは、リクエストが返される前に、すべてのサーバーが確実に更新されます。次の例では、同期ブロードキャストを構成しています。

<property name="eclipselink.cache.coordination.propagate-asynchronously"
value="false" />

同じサーバーまたはネットワーク上の複数のアプリケーションがキャッシュ・コーディネーションを使用する場合は、アプリケーションごとに別のチャネルを使用できます。次に例を示します。

<property name="eclipselink.cache.coordination.channel" value="EmployeeChannel" />

最後に、必要に応じて、サーバーが相互に検索できるようにするデフォルトのRMIマルチキャスト・ソケット・アドレスを変更します。次の例では、マルチキャスト設定を明示的に構成しています。

<property name="eclipselink.cache.coordination.rmi.announcement-delay"
value="1000" />
<property name="eclipselink.cache.coordination.rmi.multicast-group"
value="239.192.0.0" />
<property name="eclipselink.cache.coordination.rmi.multicast-group.port"
value="3121" />
<property name="eclipselink.cache.coordination.packet-time-to-live" value="2" />

10.2.1.5.4 キャッシュ・コーディネーションAPIを使用したキャッシュ・コーディネーションの構成

CommandManagerインタフェースを使用して、セッションのキャッシュ・コーディネーションをプログラムで構成します。インタフェースは、DatabaseSessionインタフェースのgetCommandManagerメソッドを使用してアクセスします。

10.2.2 タスク2: EclipseLinkの有効化の確認

EclipseLink JARファイルが、EclipseLinkアプリケーションがデプロイされているクラスタの各アプリケーション・サーバーのクラスパスに含まれていることを確認して、EclipseLinkを永続性プロバイダとして構成します。TopLinkをWebLogic ServerおよびGlassFish Serverで設定する方法の詳細は、第3章「WebLogic ServerでのTopLinkの使用」および第4章「GlassFish ServerでのTopLinkの使用」をそれぞれ参照してください。

10.2.3 タスク3: すべてのアプリケーション・サーバーがクラスタ内にあることの確認

EclipseLinkアプリケーションをホストする各アプリケーション・サーバーを含むアプリケーション・サーバー・クラスタを構成します。

注意:

TopLinkはJMSおよびRMIに依存し、アプリケーション・サーバーのクラスタ構成は使用しません。

- WebLogic Serverのクラスタ化の詳細は、『Oracle WebLogic Serverクラスタの管理』を参照してください。

- GlassFish Serverのクラスタ化の詳細は、次を参照してください。
http://download.oracle.com/docs/cd/E18930_01/html/821-2426/index.html

10.2.4 データのスケールのためのデータ・パーティション化の使用

データのパーティション化では、1つ以上のデータベース・マシンにアプリケーションのデータをスケーリングします。データのパーティション化では、同じクラスの別のセットのエンティティ・インスタンスを、別の物理データベースまたはデータベース・クラスタの別のノードにエンティティ・レベルで保存することをサポートしています。標準のデータベースもクラスタ化されたデータベースもサポートされています。データは水平にも垂直にもパーティション化できます。

パーティションは、エンティティ、リレーションシップ、問合せ、永続性ユニットで有効にできます。データのパーティション化を構成するには、@Partitioned注釈と1つ以上のパーティショニング・ポリシー注釈を使用します。表10-1では、パーティション・ポリシーについて説明します。

表10-1 パーティション・ポリシー

注釈

説明

@HashPartitioning

パーティションは、オブジェクトのID、場所、テナントなどのオブジェクトのフィールド値のハッシュからデータベース・クラスタにアクセスします。接続プール/ノード一覧に対してハッシュ索引を作成します。そのハッシュ値を持つオブジェクトに対するすべての書込みまたは読取り要求は、同じサーバーに送信されます。問合せにパラメータとしてハッシュ・フィールドが含まれない場合、すべてのサーバーに送信され結合されるか、セッションのデフォルトの処理が行われます。

@PinnedPartitioning

1つの接続プール/ノードに要求を固定します。これによりパーティショニングは垂直方向で行われるようになります。

@RangePartitioning

パーティションは、オブジェクトのID、場所、テナントなどのオブジェクトのフィールド値を使用しデータベース・クラスタにアクセスします。各サーバーには値の範囲が割り当てられます。その値を持つオブジェクトに対するすべての書込みまたは読取り要求は、同じサーバーに送信されます。問合せにパラメータとしてそのフィールドが含まれない場合、すべてのサーバーに送信され結合されるか、セッションのデフォルトの処理が行われます。

@ReplicationPartitioning

接続プール/ノードのセットに要求を送信します。このポリシーは、データベース・マシンのクラスタ間でデータをレプリケートするためのものです。変更の問合せのみがレプリケートされます。

@RoundRobinPartitioning

接続プール/ノードのセットにラウンドロビン方式で要求を送信します。このポリシーは、データベース・マシンのクラスタ全体に対して、読取り問合せの負荷を分散するために使用します。これでは、パーティショニングをサポートしないよう、データベースを完全にマシンにレプリケートする必要があります。データは、読取り専用のみであるか、書込みをレプリケートする必要があります。

@UnionPartitioning

問合せをすべての接続プールに送信し、結果を結合します。これは、ManyToManyのパーティションをまたがるリレーションシップなど、パーティショニングが使用されているときに、パーティションをまたぐ問合せやリレーションシップで使用します。

@ValuePartitioning

パーティションは、オブジェクトの場所やテナントなどのオブジェクトのフィールド値を使用しデータベース・クラスタにアクセスします。各値には特定のサーバーが割り当てられます。その値を持つオブジェクトに対するすべての書込みまたは読取り要求は、同じサーバーに送信されます。問合せにパラメータとしてフィールドが含まれない場合、すべてのサーバーに送信され結合されるか、セッションのデフォルトの処理が行われます。

@Partitioning

パーティションは、カスタム・パーティション・ポリシーを使用してデータベース・クラスタにアクセスします。PartitioningPolicyクラスを拡張するクラスを提供する必要があります。

パーティション・ポリシーとは、永続性ユニットでグローバルに命名されたオブジェクトで、複数の識別子または問合せで再利用できます。これにより、特にJPA注釈およびXMLの構成の使い勝手が向上します。

永続性ユニットのプロパティは、読取り、書込み、シーケンスの既存の構成に加え、名前付きの接続プールの追加をサポートしています。接続プールは、参加している各データベースのpersistence.xmlファイル内に定義します。パーティション・ポリシーは、その特定のアルゴリズムに基づいて適切な接続を選択します。

トランザクションにより複数のパーティションのデータが変更される場合、JTAを使用してデータが2段階でコミットされるようにする必要があります。1つのトランザクションに1つのノードのみが使用されるようEntityManagerの実装で排他接続を構成することも可能です。

次の例では、場所ごとにEmployeeデータをパーティション分割します。2つの主要サイトOttawaおよびTorontoは、それぞれ別のデータベースに保存されています。その他のすべての場所は、デフォルトのデータベースに保存されています。プロジェクトはそのIDで範囲がパーティション分割されています。ID値の各範囲は、別のデータベースに保存されます。

@Entity
@IdClass(EmployeePK.class)
@UnionPartitioning(
name="UnionPartitioningAllNodes",
replicateWrites=true)
@ValuePartitioning(
name="ValuePartitioningByLOCATION",
partitionColumn=@Column(name="LOCATION"),
unionUnpartitionableQueries=true,
defaultConnectionPool="default",
partitions={
@ValuePartition(connectionPool="node2", value="Ottawa"),
@ValuePartition(connectionPool="node3", value="Toronto")
})
@Partitioned("ValuePartitioningByLOCATION")
public class Employee {
@Id
@Column(name = "EMP_ID")
private Integer id;
@Id
private String location;
...

@ManyToMany(cascade = { PERSIST, MERGE })
@Partitioned("UnionPartitioningAllNodes")
private Collection<Project> projects;
...
}

従業員とプロジェクトのリレーションシップが、パーティションをまたぐリレーションシップの例です。従業員およびプロジェクトを別のデータベースに保存するために、結合ポリシーが使用され、結合表が各データベースにレプリケートされます。

@Entity
@RangePartitioning(
name="RangePartitioningByPROJ_ID",
partitionColumn=@Column(name="PROJ_ID"),
partitionValueType=Integer.class,
unionUnpartitionableQueries=true,
partitions={
@RangePartition(connectionPool="default", startValue="0",
endValue="1000"),
@RangePartition(connectionPool="node2", startValue="1000",
endValue="2000"),
@RangePartition(connectionPool="node3", startValue="2000")
})
@Partitioned("RangePartitioningByPROJ_ID")
public class Project {
@Id
@Column(name="PROJ_ID")
private Integer id;
...
}

10.2.4.1 クラスタ化されたデータベースおよびOracle RAC

一部のデータベースでは、複数のサーバーにデータベースをクラスタリングできます。Oracle Real Application Clusters (RAC)では1つのデータベースを別の複数のサーバー・ノードにスパンできます。Oracle RACでは、データを表およびノードでパーティション化することも可能です。データベース・クラスタを使用すると、クラスタの任意のノードから任意のデータにアクセスできます。ただし、一般的には、ノード間での通信を減らすために、データへのアクセスを特定のノードにパーティション化する方が効率的です。パーティション化を、クラスタ・データベースとともに使用すると、ノード間の通信を減らし、拡張性を向上させることができます。Oracle RACでEclipseLinkを使用する方法の詳細は、24.2.5項「Oracle RACでのEclipseLinkの使用」を参照してください。

データベース・クラスタでデータのパーティション化を使用する際の要件は、次のとおりです。

- データベース・クラスタによりすべてのノードがデータを利用できるようになってしまうので、パーティション・ポリシーでは、レプリケーションを有効にしないようにする必要があります。

- データベース・クラスタによりすべてのノードの問合せ結果がすべて返されてしまうので、パーティション・ポリシーでは結合を使用しないようにする必要があります。

- クラスタの各ノードにDataSourceおよび接続プールを定義する必要があります。

- アプリケーションのデータ・アクセスおよびデータ・パーティション化で、各トランザクションが1つのノードにのみアクセスするよう設計する必要があります。

- 1つのトランザクションで複数のノードがあったり、2段階でのコミットを避けるは、EntityManagerで排他接続を使用することが推奨されます。

10.3 その他の参考資料

この章のソリューションが実装されているその他のテクノロジおよびツールの詳細は、次の参考資料を参照してください。

次のコード例およびJavaDocの参考資料を参照できます。

- コード例

- http://wiki.eclipse.org/EclipseLink/Examples/JPA/CacheCoordination

- http://wiki.eclipse.org/EclipseLink/Examples/JPA/Caching

- 『Oracle TopLink Java APIリファレンス』で次のAPIに関する項を参照してください。

- org.eclipse.persistence.annotations.OptimisticLocking

- org.eclipse.persistence.annotations.Cache

- org.eclipse.persistence.annotations.Partitioned

- org.eclipse.persistence.descriptors.ClassDescriptor

- org.eclipse.persistence.sessions.coordination

11 Software as a Serviceの提供

この章では、Saas環境で実行する共有アプリケーションを開発するために使用できるOracle TopLinkの機能について説明します。

ユース・ケース

アプリケーションおよびデータが、複数のクライアントによって共有されるSaaS環境をユーザーが構築したいと考えています。

解決方法

拡張性、クライアント分離、外部メタデータ・ソースなど、TopLinkのSaaS機能を使用します。

コンポーネント

- TopLink 12cリリース1 (12.1.2)以上。

注意:

TopLinkのコア機能は、オープン・ソースのEclipse Foundationの永続性フレームワークであるEclipseLinkによって提供されています。EclipseLinkでは、Java Persistence API (JPA)、Java Architecture for XML Binding (JAXB)、および標準に基づいたその他の永続性テクノロジと、それらの標準の拡張が実装されます。TopLinkには、EclipseLinkのすべてに加え、Oracleの追加機能が含まれています。

11.1 ソリューションの概要

SaaS用のOracleプラットフォームには、Oracle Fusion Middlewareの一部であるTopLinkが含まれます。これにより、SaaSアプリケーションのビルド、デプロイおよび管理が可能になっています。TopLinkでは、クラウド対応のアプリケーションおよびサービスで永続性を管理できます。TopLinkでは、クライアントの分離、拡張性、外部メタデータ・ソースに対応する柔軟なSaaSソリューションを提供しながら、これらのアプリケーションの永続性レイヤーを重要なコンポーネントにする、高いパフォーマンスとスケーラビリティを維持しています。

これらの機能は、次の章で説明します。

- 第12章「JPAエンティティおよびJAXB Beanの拡張可能化」

- 第13章「外部メタデータ・ソースの使用」

- 第14章「TopLinkを使用したテナントの分離」

12 JPAエンティティおよびJAXB Beanの拡張可能化

この章では、JPAエンティティおよびJAXB Beanを拡張可能にする方法を説明します。エンティティまたはBeanのソース・ファイルを変更したり、永続性ユニットの再デプロイをしなくても、外部でマッピングを追加したり変更できます。この機能は、複数のクライアントがアプリケーションおよびデータ・ソースを共有するSoftware-as-a-Service環境で便利です。また、デプロイ時ではなく、インストール時にアプリケーションをカスタマイズする際にも便利です。

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

- 12.1項「JPAエンティティの拡張可能化」

- 12.2項「JAXB Beanの拡張可能化」

- 12.3項「その他の参考資料」

ユース・ケース

アプリケーションおよびデータ・ソースが複数のクライアントにより共有されるSaaS環境をユーザーが構築したいと考えています。

解決方法

TopLinkの拡張機能を使用し、外部マッピングを使用してJPAエンティティおよびJAXB Beanを拡張します。

コンポーネント

- TopLink 12cリリース1 (12.1.2)以上。

注意:

TopLinkのコア機能は、オープン・ソースのEclipse Foundationの永続性フレームワークであるEclipseLinkによって提供されています。EclipseLinkでは、Java Persistence API (JPA)、Java Architecture for XML Binding (JAXB)、および標準に基づいたその他の永続性テクノロジと、それらの標準の拡張が実装されます。TopLinkには、EclipseLinkのすべてに加え、Oracleの追加機能が含まれています。

12.1 JPAエンティティの拡張可能化

@VirtualAccessMethods注釈を使用して、エンティティが拡張可能であることを指定します。拡張可能なエンティティで仮想プロパティを使用すれば、エンティティの外部でマッピングを指定できます。これにより、エンティティのソース・ファイルの変更およびエンティティの永続性ユニットの再デプロイをしなくても、マッピングを変更できるようになります。

拡張可能なエンティティは、複数のクライアント(テナント)が共有の汎用アプリケーションを使用するマルチテナント(SaaS)アーキテクチャで便利です。テナントは、自分のデータにプライベートにアクセスでき、他のテナントと共有するデータにもアクセスできます。

拡張可能なエンティティを使用すれば、次のことを行えます。

- 一部のマッピングがすべてのユーザーに共通で、一部のマッピングはユーザー固有であるようなアプリケーションを作成できます。

- 顧客に提供された後のアプリケーションにマッピングを追加できます(デプロイメント後でも可能)。

- マッピングの変更後も、同じEntityManagerFactoryインタフェースを使用してデータを操作できます。

- アプリケーションで使用されるメタデータのソースを追加提供できます。

12.1.1 拡張可能なJPAエンティティを作成およびサポートするための主要タスク

拡張可能なJPAエンティティを作成およびサポートするには:

- タスク1: エンティティの構成

- タスク2: スキーマの設計

- タスク3: 追加マッピングの提供

- タスク4: MetaDataSourceを使用した拡張の外部化

12.1.1.1 タスク1: エンティティの構成

エンティティを構成するには、次の項で説明するとおり、エンティティ・クラスを@VirtualAccessMethodsで注釈指定し(またはXML <access-methods>を使用し)、プロパティ値にgetおよびsetメソッドを追加し、拡張した属性と値をストアするデータ構造を追加します。

- 12.1.1.1.1項「@VirtualAccessMethodsによるエンティティ・クラスの注釈指定」

- 12.1.1.1.2項「エンティティに対するgetおよびsetメソッドの追加」

- 12.1.1.1.3項「仮想属性のストアの定義」

- 12.1.1.1.4項「XMLの使用」

12.1.1.1.1 @VirtualAccessMethodsによるエンティティ・クラスの注釈指定

@VirtualAccessMethodsでエンティティに注釈を付けて、エンティティが拡張可能であることを指定し、仮想プロパティを定義します。

表12-1は、@VirtualAccessMethods注釈で使用可能な属性を説明しています。

表12-1 @VirtualAccessMethods注釈の属性

属性

説明

get

仮想プロパティに使用するgetterメソッドの名前。このメソッドは、1つのjava.lang.Stringパラメータを受け取ってjava.lang.Objectパラメータを返す必要があります。

デフォルト: get

必須かどうか: いいえ

set

仮想プロパティに使用するsetterメソッドの名前。このメソッドは、java.lang.Stringおよびjava.lang.Objectパラメータを受け取ってjava.lang.Objectパラメータを返す必要があります。

デフォルト: set

必須かどうか: いいえ

12.1.1.1.2 エンティティに対するgetおよびsetメソッドの追加

エンティティに対して、get(String)およびset(String, Object)メソッドを追加します。get()メソッドは、プロパティ名によって値を返し、set()メソッドはプロパティ名によって値をストアします。これらのメソッドのデフォルト名は、getおよびsetで、@VirtualAccessMethods注釈でオーバーライドできます。

EclipseLinkでは、ウィービングが有効な場合に、これらのメソッドがウィービングされて、遅延ロード、変更追跡、フェッチ・グループおよび内部最適化がサポートされます。

注意:

OneToOneマッピングで仮想アクセス・メソッドを使用する場合、ウィービングはサポートされません。使用すると、例外がスローされます。

12.1.1.1.3 仮想属性のストアの定義

拡張された属性と値、つまり仮想マッピングをストアするデータ構造を追加します。その後、これらをデータベースにマップできます。12.1.1.3項「タスク3: 追加マッピングの提供」を参照してください。

仮想マッピングは(例12-1に示されているような)Mapオブジェクトにストアするのが一般的ですが、他の戦略を使用することもできます。

フィールドベースのアクセスを使用する際には、@Transientでデータ構造に注釈を付けて、この構造を別のマッピングに使用できないようにします。プロパティベースのアクセスを使用する場合、@Transientは不要です。

例12-1に、プロパティ・アクセスを使用するエンティティ・クラスを示します。

例12-1 プロパティ・アクセスを使用するエンティティ・クラス

@Entity
@VirtualAccessMethods
public class Customer{

@Id
private int id;
...

@Transient
private Map<String, Object> extensions;

public <T> T get(String name) {
return (T) extentions.get(name);
}

public Object set(String name, Object value) {
return extensions.put(name, value);
}

12.1.1.1.4 XMLの使用

@VirtualAccessMethods注釈を使用する方法に加えて、代替方法として、たとえば次などのように、(<basic>などの)マッピング要素にaccess="VIRTUAL"を使用できます。

<basic name="idNumber" access="VIRTUAL" attribute-type="String">
<column name="FLEX_COL1"/>
</basic>

永続性ユニットのデフォルトとして仮想アクセス方法を設定するには、たとえば次などのように<access>および<access-methods>要素を使用します。

<persistence-unit-metadata>
<xml-mapping-metadata-complete/>
<exclude-default-mappings/>
<persistence-unit-defaults>
<access>VIRTUAL</access>
<access-methods set-method="get" get-method="set"/>
</persistence-unit-defaults>
</persistence-unit-metadata>

12.1.1.2 タスク2: スキーマの設計

データベース表に仮想属性値をストアする追加の列を用意します。たとえば、次のCustomer表には、事前定義されたIDとNAMEの2つの列があり、属性値をストアするEXT_1、EXT_2、EXT_3の3つの列があります。

CUSTOMER表

- INTEGER ID

- VARCHAR NAME

- VARCHAR EXT_1

- VARCHAR EXT_2

- VARCHAR EXT_3

次に、「タスク3: 追加マッピングの提供」に説明されているように、拡張された属性を永続化するために、どのFLEX列を使用するかを指定できます。

12.1.1.3 タスク3: 追加マッピングの提供

追加マッピングを提供するには、columnおよびaccess-methods属性が指定されたマッピングをeclipselink-orm.xmlファイルに追加します。次に例を示します。

<basic name="idNumber" access="VIRTUAL" attribute-type="String">
<column name="FLEX_COL1"/>
</basic>

12.1.1.4 タスク4: MetaDataSourceを使用した拡張の外部化

永続性ユニット・プロパティを構成して、アプリケーションがeclipselink-orm.xmlファイルからフレキシブル・マッピングを取得する必要があることを示します。次の項に説明されているように、persistence.xmlファイルを使用するか、EntityManagerFactoryインタフェースにプロパティを設定して、永続性ユニット・プロパティを設定できます。

外部マッピングの詳細は、13章「外部メタデータ・ソースの使用」を参照してください。

12.1.1.4.1 persistence.xmlファイルの構成

デフォルトのeclipselink-orm.xmlファイルを使用するために、persistence.xmlファイルでeclipselink.metadata-sourceプロパティを使用します。指定した場所にある別のファイルを使用するには、eclipselink.metadata-source.xml.urlプロパティを使用します。次に例を示します。

<property name="eclipselink.metadata-source" value="XML"/>
<property name="eclipselink.metadata-source.xml.url" value="foo://bar"/>

12.1.1.4.2 EntityManagerFactoryおよびメタデータ・リポジトリの構成

拡張機能は、ブートストラップ時にメタデータ・リポジトリにアクセスして追加されます。メタデータ・リポジトリには、そこに保持されているメタデータを取得するメソッドを提供するクラスを介してアクセスします。EclipseLinkには、XMLリポジトリをサポートするメタデータ・リポジトリが実装されています。

メタデータ・リポジトリに対して使用するクラスおよび構成情報を永続性ユニット・プロパティに指定します。EntityManagerFactoryインタフェースでは、メタデータ・リポジトリの追加マッピング情報が、ブートストラップに使用されるメタデータに統合されます。

独自のクラスの実装を用意して、メタデータ・リポジトリにアクセスできます。各メタデータ・リポジトリ・アクセス・クラスには、リポジトリに接続するために使用するプロパティのセットを個別に指定する必要があります。

次のクラスのどちらかをサブクラスにできます。

- org.eclipse.persistence.internal.jpa.extensions.MetadataRepository

- org.eclipse.persistence.internal.jpa.extensions.XMLMetadataRepository

次の例では、com.fooで始まるプロパティが、開発者によって定義されたサブクラスです。

<property name="eclipselink.metadata-source" value="com.foo.MetadataRepository"/>
<property name="com.foo.MetadataRepository.location" value="foo://bar"/>
<property name="com.foo.MetadataRepository.extra-data" value="foo-bar"/>

12.1.1.4.3 メタデータ・リポジトリのリフレッシュ

メタデータを変更した場合に、新しいメタデータに基づくEntityManagerインスタンスが必要なときは、EntityManagerFactoryインタフェースでrefreshMetadata()メソッドを呼び出してデータをリフレッシュします。次のEntityManagerインスタンスは、新しいメタデータに基づいています。

refreshMetadata()メソッドは、それ以前にmetadata-source要素に対して定義されていたプロパティをオーバーライドするために使用できるプロパティ・マップをとります。

12.1.2 コード例

例12-2は、次のことを示しています。

- 非拡張フィールドには、フィールド・アクセスが使用されています。

- 拡張フィールドには、デフォルト(get(String)およびset(String, Object))を使用した仮想アクセスが使用されています。

- get(String)およびset(String, Object)メソッドは、マッピングで使用されていなくても、@VirtualAccessMethodsが指定されているので、ウィービングされます。

これらの項目は、太字のフォントで示します。

例12-2 デフォルトのgetおよびsetメソッド名を使用した仮想アクセス

@Entity
@VirtualAccessMethods
public class Address {

@Id
private int id;

@Transient
private Map<String, Object> extensions;

public int getId(){
return id;
}

public <T> T get(String name) {
return (T) extentions.get(name);
}

public Object set(String name, Object value) {
return extensions.put(name, value);
}
.
.
.

例12-3は、次のことを示しています。

- 非拡張フィールドには、フィールド・アクセスが使用されています。

- getおよびsetに使用されるメソッドを@VirtualAccessMethods注釈でオーバーライドしています。

- get(String)およびset(String, Object)メソッドは、マッピングで使用されていなくても、@VirtualAccessMethodsが指定されているので、ウィービングされます。

- get()およびset()メソッドのどちらを使用するかを、拡張マッピングのXMLで示しています。

これらの項目は、太字のフォントで示します。

例12-3 getおよびsetメソッドのオーバーライド

@Entity
@VirtualAccessMethods(get="getExtension", set="setExtension")
public class Address {

@Id
private int id;

@Transient
private Map<String, Object> extensions;

public int getId(){
return id;
}

public <T> T getExtension(String name) {
return (T) extensions.get(name);
}

public Object setExtension(String name, Object value) {
return extensions.put(name, value);
}

...

<basic name="name"  access="VIRTUAL" attribute-type="String">
<column name="FLEX_1"/>
</basic>

例12-4は、次のことを示しています。

- 非拡張フィールドには、プロパティ・アクセスが使用されています。

- 拡張フィールドには、デフォルト(get(String)およびset(String, Object))を使用した仮想アクセスが使用されています。

- 拡張機能は移植可能な方法でマッピングされています。プロパティ・アクセスが使用されるので、@Transientは不要です。

- get(String)およびset(String, Object)メソッドは、マッピングで使用されていなくても、@VirtualAccessMethodsが指定されているので、ウィービングされます。

これらの項目は、太字のフォントで示します。

例12-4 プロパティ・アクセスの使用

@Entity
@VirtualAccessMethods
public class Address {

private int id;

private Map<String, Object> extensions;

@Id
public int getId(){
return id;
}

public <T> T get(String name) {
return (T) extensions.get(name);
}

public Object set(String name, Object value) {
return extensions.put(name, value);
}

...

12.2 JAXB Beanの拡張可能化

@XmlVirtualAccessMethods注釈を使用して、JAXB Beanが拡張可能であることを指定します。拡張可能なBeanで仮想プロパティを使用すれば、Beanの外部でマッピングを指定できます。これにより、Beanのソース・ファイルの変更およびBeanの永続性ユニットの再デプロイをしなくても、マッピングを変更できるようになります。

マルチテナント(またはSaaS)アーキテクチャでは、サーバーで1つのアプリケーションが動作して、複数のクライアント組織(テナント)にサービスを提供します。優れたマルチテナント・アプリケーションでは、テナントごとのカスタマイズが可能です。これらのカスタマイズがデータに対して行われる場合は、バインディング・レイヤーでカスタマイズを処理するのが難しい場合があります。JAXBは、実際のフィールドおよびプロパティがあるドメイン・モデルを操作するように設計されています。EclipseLinkのJAXBに対する拡張には、このユース・ケースを簡単に扱う仮想プロパティの概念が導入されています。仮想プロパティはObject-XMLメタデータ・ファイルによって定義されているので、ソースを変更しなくてもクラスを拡張できます。

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

- 12.2.1項「主な手順」

- 12.2.2項「コード例」

12.2.1 主な手順

拡張可能なJAXB Beanを作成およびサポートするには:

- タスク1: Beanの構成

- タスク2: 追加マッピングの提供

12.2.1.1 タスク1: Beanの構成

Beanを構成するには、Beanクラスを@XmlVirtualAccessMethodsで注釈指定し、プロパティ値にgetおよびsetメソッドを追加し、拡張した属性と値をストアするデータ構造を追加します。または、eclipselink-orm.xmlで<xml-virtual-access-methods>要素を使用します。

12.2.1.1.1 @Xml VirtualAccessMethodsによるBeanクラスの注釈指定

@XmlVirtualAccessMethodsでBeanに注釈を付けて、Beanが拡張可能であることを指定し、仮想プロパティを定義します。

表12-2は、@XmlVirtualAccessMethods注釈で使用可能な属性を説明しています。

表12-2 @XmlVirtualAccessMethods注釈の属性

属性

説明

get

仮想プロパティに使用するgetterメソッドの名前。このメソッドは、1つのjava.lang.Stringパラメータを受け取ってjava.lang.Objectを返す必要があります。

デフォルト: get

必須かどうか: いいえ

set

仮想プロパティに使用するsetterメソッドの名前。このメソッドは、java.lang.Stringおよびjava.lang.Objectパラメータを受け取ってjava.lang.Objectパラメータを返す必要があります。

デフォルト: set

必須かどうか: いいえ

12.2.1.1.2 Beanに対するgetおよびsetメソッドの追加

Beanに対して、get(String)およびset(String, Object)メソッドを追加します。get()メソッドは、プロパティ名によって値を返し、set()メソッドはプロパティ名によって値をストアします。これらのメソッドのデフォルト名は、getおよびsetで、@XmlVirtualAccessMethods注釈でオーバーライドできます。

12.2.1.1.3 仮想属性のストアの定義

拡張された属性と値、つまり仮想マッピングをストアするデータ構造を追加します。その後、これらをデータベースにマップできます。「タスク2: 追加マッピングの提供」を参照してください。

仮想マッピングはMapにストアするのが一般的ですが、他の方式を使用することもできます。たとえば、ディレクトリ・システムに仮想マッピングをストアすることもできます。

フィールドベースのアクセスを使用する際には、@XmlTransientでデータ構造に注釈を付けて、この構造を別のマッピングに使用できないようにします。プロパティベースのアクセスを使用する場合、@XmlTransientは不要です。

12.2.1.1.4 XMLの使用

@XmlVirtualAccessMethodsを使用する方法に加えて、代替方法として、同等のXMLを、次のように使用することもできます。

- getおよびsetを使用する仮想アクセス・メソッドを有効にするXML:

<xml-virtual-access-methods/>

- setではなくputを使用する仮想アクセス・メソッドを有効にするXML(デフォルト):

<xml-virtual-access-methods set-method="put"/>

- getではなくretrieveを使用する仮想アクセス・メソッドを有効にするXML(デフォルト):

<xml-virtual-access-methods get-method="retrieve"/>

- getとsetではなくretrieveとputを使用する仮想アクセス・メソッドを有効にするXML(デフォルト):

<xml-virtual-access-methods get-method="retrieve" set-method="put"/>

12.2.1.2 タスク2: 追加マッピングの提供

追加マッピングを提供するには、マッピングをeclipselink-oxm.xmlファイルに追加します。次に例を示します。

<xml-element java-attribute="idNumber"/>

12.2.2 コード例

この項の例は、拡張可能なJAXB Beanを使用する方法を示します。この例では、他のクラスが拡張できるベース・クラスを最初に作成します。この場合、拡張可能なクラスは、CustomersおよびPhoneNumbers用です。マッピング・ファイルは2つの個別のテナントに対して作成されています。両方のテナントはいくつかの実際のプロパティを共有していますが、それぞれの要件に固有の仮想プロパティを定義します。

12.2.2.1 基本設定

例12-5は、他の拡張可能なクラスが拡張できるベース・クラスExtensibleBaseを示しています。この例では、@XmlTransient注釈を使用することにより、ExtensibleBaseが継承関係としてマップされないようにしています。モデル内で、すべてのテナントに共通な部分は、実際のプロパティで表されます。テナントごとの拡張機能は、仮想プロパティとして表されます。

例12-5 拡張可能なクラスのベース・クラス

package examples.virtual;

import java.util.HashMap;
import java.util.Map;

import javax.xml.bind.annotation.XmlTransient;

import org.eclipse.persistence.oxm.annotations.XmlVirtualAccessMethods;

@XmlTransient
@XmlVirtualAccessMethods(setMethod="put")
public class ExtensibleBase {

private Map<String, Object> extensions = new HashMap<String, Object>();

public <T> T get(String property) {
return (T) extensions.get(property);
}

public void put(String property, Object value) {
extensions.put(property, value);
}
}

例12-6に、Customerクラスの定義を示します。Customerクラスは、@XmlVirtualAccessMethods注釈が付けられたドメイン・クラスから継承するので拡張可能です。

例12-6 拡張可能なCustomerクラス

package examples.virtual;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Customer extends ExtensibleBase {

private String firstName;
private String lastName;
private Address billingAddress;

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

public Address getBillingAddress() {
return billingAddress;
}

public void setBillingAddress(Address billingAddress) {
this.billingAddress = billingAddress;
}

}

例12-7に、Addressクラスを示します。モデル内のすべてのクラスを拡張可能にする必要はありません。この例のAddressクラスには、仮想プロパティはありません。

例12-7 拡張可能ではないAddressクラス

package examples.virtual;

public class Address {

private String street;

public String getStreet() {
return street;
}

public void setStreet(String street) {
this.street = street;
}

}

例12-8に、PhoneNumberクラスを示します。Customerと同様に、PhoneNumberは拡張可能なクラスになります。

例12-8 拡張可能なPhoneNumberクラス

package examples.virtual;

import javax.xml.bind.annotation.XmlValue;

public class PhoneNumber extends ExtensibleBase {

private String number;

@XmlValue
public String getNumber() {
return number;
}

public void setNumber(String number) {
this.number = number;
}

}

12.2.2.2 テナントの定義

この項の例では、2つの個別のテナントが定義されています。両方のテナントはいくつかの実際のプロパティを共有していますが、仮想プロパティが指定されているので、対応するXML表現はまったく異なるものにできます。

テナント1

最初のテナントは、オンライン・スポーツ用品店で、次のようにモデルを拡張する必要があります。

- 顧客ID

- 顧客のミドル・ネーム

- 配送先住所

- 連絡先電話番号のコレクション

- 電話番号のタイプ(自宅、勤務先、または携帯など)

仮想プロパティのメタデータは、eclipselink-oxm.xmlマッピング・ファイルまたはeclipselink-orm.xmlスキーマを使用するファイルにキャプチャされます。仮想プロパティは、実際のプロパティと同様の方法でマップされます。タイプ(リフレクションでは特定できないため)、およびコレクション・プロパティの場合はコンテナ・タイプなど、追加情報がいくらか必要です。次に定義されているCustomerの仮想プロパティは、middleName、shippingAddressおよびphoneNumbersです。PhoneNumberの仮想プロパティはtypeプロパティです。

例12-9に、binding-tenant1.xmlマッピング・ファイルを示します。

例12-9 テナント1の仮想プロパティの定義

<?xml version="1.0"?>
<xml-bindings
xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
package-name="examples.virtual">
<java-types>
<java-type name="Customer">
<xml-type prop-order="firstName middleName lastName billingAddress shippingAddress phoneNumbers"/>
<java-attributes>
<xml-attribute
java-attribute="id"
type="java.lang.Integer"/>
<xml-element
java-attribute="middleName"
type="java.lang.String"/>
<xml-element
java-attribute="shippingAddress"
type="examples.virtual.Address"/>
<xml-element
java-attribute="phoneNumbers"
name="phoneNumber"
type="examples.virtual.PhoneNumber"
container-type="java.util.List"/>
</java-attributes>
</java-type>
<java-type name="PhoneNumber">
<java-attributes>
<xml-attribute
java-attribute="type"
type="java.lang.String"/>
</java-attributes>
</java-type>
</java-types>
</xml-bindings>

getおよびsetメソッドは、実際のプロパティを操作するためにドメイン・モデルで使用し、@XmlVirtualAccessMethods注釈に定義されているアクセッサは、仮想プロパティを操作するために使用します。通常のJAXBメカニズムは、操作のマーシャルおよびアンマーシャルに使用します。例12-10に、仮想プロパティに関連付けられているデータを取得するための、テナント1のCustomerクラスのコードを示します。

例12-10 仮想プロパティに関連付けられているデータを提供するためのテナント1のコード

...
Customer customer = new Customer();

//Set Customer's real properties
customer.setFirstName("Jane");
customer.setLastName("Doe");

Address billingAddress = new Address();
billingAddress.setStreet("1 Billing Street");
customer.setBillingAddress(billingAddress);

//Set Customer's virtual 'middleName' property
customer.put("middleName", "Anne");

//Set Customer's virtual 'shippingAddress' property
Address shippingAddress = new Address();
shippingAddress.setStreet("2 Shipping Road");
customer.put("shippingAddress", shippingAddress);

List<PhoneNumber> phoneNumbers = new ArrayList<PhoneNumber>();
customer.put("phoneNumbers", phoneNumbers);

PhoneNumber workPhoneNumber = new PhoneNumber();
workPhoneNumber.setNumber("555-WORK");
//Set the PhoneNumber's virtual 'type' property
workPhoneNumber.put("type", "WORK");
phoneNumbers.add(workPhoneNumber);

PhoneNumber homePhoneNumber = new PhoneNumber();
homePhoneNumber.setNumber("555-HOME");
//Set the PhoneNumber's virtual 'type' property
homePhoneNumber.put("type", "HOME");
phoneNumbers.add(homePhoneNumber);

Map<String, Object> properties = new HashMap<String, Object>();
properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, "examples/virtual/binding-tenant1.xml");
JAXBContext jc = JAXBContext.newInstance(new Class[] {Customer.class, Address.class}, properties);

Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(customer, System.out);
...

例12-11に、テナント1のCustomerクラスからのXML出力を示します。

例12-11 テナント1のCustomerクラスからのXML出力

<?xml version="1.0" encoding="UTF-8"?>
<customer>
<firstName>Jane</firstName>
<middleName>Anne</middleName>
<lastName>Doe</lastName>
<billingAddress>
<street>1 Billing Street</street>
</billingAddress>
<shippingAddress>
<street>2 Shipping Road</street>
</shippingAddress>
<phoneNumber type="WORK">555-WORK</phoneNumber>
<phoneNumber type="HOME">555-HOME</phoneNumber>
</customer>

テナント2

2番目のテナントは、オンデマンドの映画や音楽を提供するストリーミング・メディア・プロバイダです。ここでは、コア・モデルに対して別のセットの拡張機能が必要になります。

- 1つの連絡先電話番号

このテナントの場合、実際のプロパティのマッピングのカスタマイズにもマッピング・ファイルを使用します。

例12-12に、binding-tenant2.xmlマッピング・ファイルを示します。

例12-12 テナント2の仮想プロパティの定義

<?xml version="1.0"?>
<xml-bindings
xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
package-name="examples.virtual">
<xml-schema namespace="urn:tenant1" element-form-default="QUALIFIED"/>
<java-types>
<java-type name="Customer">
<xml-type prop-order="firstName lastName billingAddress phoneNumber"/>
<java-attributes>
<xml-attribute java-attribute="firstName"/>
<xml-attribute java-attribute="lastName"/>
<xml-element java-attribute="billingAddress" name="address"/>
<xml-element
java-attribute="phoneNumber"
type="examples.virtual.PhoneNumber"/>
</java-attributes>
</java-type>
</java-types>
</xml-bindings>

例12-13に、仮想プロパティに関連付けられているデータを取得するための、テナント2のCustomerクラスのコードを示します。

例12-13 仮想プロパティに関連付けられているデータを提供するためのテナント2のコード

...
Customer customer = new Customer();
customer.setFirstName("Jane");
customer.setLastName("Doe");

Address billingAddress = new Address();
billingAddress.setStreet("1 Billing Street");
customer.setBillingAddress(billingAddress);

PhoneNumber phoneNumber = new PhoneNumber();
phoneNumber.setNumber("555-WORK");
customer.put("phoneNumber", phoneNumber);

Map<String, Object> properties = new HashMap<String, Object>();
properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, "examples/virtual/binding-tenant2.xml");
JAXBContext jc = JAXBContext.newInstance(new Class[] {Customer.class, Address.class}, properties);

Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(customer, System.out);
...

例12-14に、テナント2のCustomerクラスからのXML出力を示します。

例12-14 テナント2のCustomerクラスからのXML出力

<?xml version="1.0" encoding="UTF-8"?>
<customer xmlns="urn:tenant1" firstName="Jane" lastName="Doe">
<address>
<street>1 Billing Street</street>
</address>
<phoneNumber>555-WORK</phoneNumber>
</customer>

12.3 その他の参考資料

この章のソリューションが実装されているその他のテクノロジおよびツールの詳細は、次の参考資料を参照してください。

- コード例

- http://wiki.eclipse.org/EclipseLink/Examples/MySports

- 『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』の@VirtualAccessMethods

- Oracle TopLinkによるJAXBアプリケーションの開発の仮想アクセスの方法の定義に関する項

13 外部のメタデータ・ソースの使用

この章では、デプロイ済のアプリケーションで動的にマッピングをオーバーライドしたり拡張するために、実行中のアプリケーションに対して外部のメタデータ・ソースにマッピング情報をストアする手順について説明します。

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

- 13.1項「ソリューションの概要」

- 13.2項「eclipselink-orm.xmlファイルの外部使用」

- 13.3項「主なタスク」

- 13.4項「その他の参考資料」

ユース・ケース

アプリケーションが複数のクライアントにより共有されるSaaS環境をユーザーが構築したいと考えています。

解決方法

拡張性、マルチテナント、外部メタデータ・ソースなど、TopLinkのSaaS機能を採用します。

コンポーネント

- TopLink 12cリリース1 (12.1.2)以上。

注意:

TopLinkのコア機能は、オープン・ソースのEclipse Foundationの永続性フレームワークであるEclipseLinkによって提供されています。EclipseLinkでは、Java Persistence API (JPA)、Java Architecture for XML Binding (JAXB)、および標準に基づいたその他の永続性テクノロジと、それらの標準の拡張が実装されます。TopLinkには、EclipseLinkのすべてに加え、Oracleの追加機能が含まれています。

13.1 ソリューションの概要

実行中のアプリケーションの外部にあるメタデータ・ソースにマッピング情報をストアできます。マッピング情報は、アプリケーションが永続性ユニットを作成するときに取得されるので、デプロイされたアプリケーションで動的にマッピングのオーバーライドまたは拡張を行えます。

13.2 eclipselink-orm.xmlファイルの外部使用

EclipseLinkでは、eclipselink-orm.xmlファイルを使用し、高度なマッピングのタイプおよびオプションをサポートできます。このファイルで、標準のJPA orm.xmlマッピング構成ファイルをオーバーライドできます。

13.3 主なタスク

外部のメタデータ・ソースをマッピング情報に使用するには、次のタスクを実行します。

- タスク1: 永続性ユニットの構成

- タスク2: サーバーの構成

13.3.1 タスク1: 永続性ユニットの構成

永続性ユニットで、eclipselink.metadata.sourceプロパティを定義して外部のメタデータ・ソースを指定し、その値にorg.eclipse.persistence.jpa.metadata.MetadataSourceを実装するクラスを割り当てます。次に例を示します。

<property name="eclipselink.metadata-source" value="mypackage.MyMetadataSource"/>

たとえば次などのように、クラスでメタデータに任意の場所を自由に用意できます。

public class AdminMetadataSource extends XMLMetadataSource {

@Override
public XMLEntityMappings getEntityMappings(Map<String, Object> properties, ClassLoader classLoader, SessionLog log) {
String leagueId = (String) properties.get(LEAGUE_CONTEXT);
properties.put(PersistenceUnitProperties.METADATA_SOURCE_XML_URL, "http://myserverlocation/rest/" + leagueId + "/orm");
return super.getEntityMappings(properties, classLoader, log);
}
}

13.3.2 タスク2: サーバーの構成

メタデータ・ファイルにアクセスするには、次のいずれかの方法を使用して、サーバーでマッピング・ファイルへURLでアクセスできる必要があります。

- 静的なファイル提供サービス

- 独自のマッピング・ファイルを使用するサーバーベースのソリューションまたは、ストアされたマッピング情報を使用するオンデマンドで作成されるマッピング・ファイル

- その他のWebテクノロジ

13.4 その他の参考資料

この章のソリューションを実装するその他のテクノロジおよびツールの詳細は、次の参考資料を参照してください。

- JPAデプロイメントの詳細は、JPA仕様の次の項(http://jcp.org/en/jsr/detail?id=317)を参照してください。

- 7.2項「Bootstrapping in Java SE Environments」

- 第7章「Container and Provider Contracts for Deployment and Bootstrapping」

- 永続性ユニットのプロパティの詳細は、『Oracle Fusion Middleware EclipseLink Java APIリファレンス』のPersistenceUnitPropertiesクラスに関する項を参照してください。

- APIの詳細は、『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』で次を参照してください。

- metadata-source

- metadata-source.properties.file

- metadata-source.send-refresh-command

- metadata-source.xml.file

- metadata-source.xml.url

14 TopLinkを使用したテナントの分離

Oracle TopLinkでは、アプリケーションを1つ開発し、それを別の複数のクライアント(つまりテナント)に、アプリケーションの割合、データの分離度およびテナントに固有の機能を変えてデプロイできます。たとえば、規模の大きな企業が1つの給与アプリケーションを、複数の部門で使用するよう開発したとします。各部門は、独自のデータと共有データにアクセスできますが、他の部門のデータはまったく参照することができません。

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

- 14.1項「ソリューションの概要」

- 14.2項「単一表マルチテナントの使用」

- 14.3項「テナントごとの表マルチテナントの使用」

- 14.4項「VPDマルチテナントの使用」

- 14.5項「その他の参考資料」

ユース・ケース

Saas環境などで、アプリケーションの複数のクライアントで、データ・ソースを共有しながら、自分のデータにはプライベートにアクセスできる必要があります。

解決方法

テナントを分離する戦略を決定し、TopLinkのテナントの分離機能を使用してその戦略を導入します。

コンポーネント

- TopLink 12cリリース1 (12.1.2)以上。

注意:

TopLinkのコア機能は、オープン・ソースのEclipse Foundationの永続性フレームワークであるEclipseLinkによって提供されています。EclipseLinkでは、Java Persistence API (JPA)、Java Architecture for XML Binding (JAXB)、および標準に基づいたその他の永続性テクノロジと、それらの標準の拡張が実装されます。TopLinkには、EclipseLinkのすべてに加え、Oracleの追加機能が含まれています。

- Oracle Database、Oracle Express、MySQLなどの対応するJava Database Connectivity (JDBC)データベース。

14.1 ソリューションの概要

EclipseLinkでは、テナントを分離する機能の設計および実装をかなり柔軟にできます。次などが可能です。

アプリケーションの分離オプション

- コンテナ/サーバーの分離

- 同じコンテナ/サーバー内でアプリケーションを分離

- 同じアプリケーション内でエンティティ・マネージャ・ファクトリおよび共有キャッシュを分離

- エンティティ・マネージャごとにテナントは分離し、エンティティ・マネージャ・ファクトリは共有

データの分離オプション

- データベースの分離

- スキーマ/表領域の分離

- 表の分離

- 表は共有し列を分離

- 問合せのフィルタリング

- Oracle仮想プライベート・データベース(VPD)

EclipseLinkには、データ・ソースでマルチテナンシを提供する次のオプションがあります。

- 単一表マルチテナントでは、テナントは表を共有できます。各テナントは識別子列によって識別される独自の行を持ち、それらの列は他のテナントは参照できません。「単一表マルチテナントの使用」を参照してください。

- テナントごとの表マルチテナントでは、各テナントは表テナント識別子で識別される独自の表を持ち、それらの表は他のユーザーは参照できません。「テナントごとの表マルチテナントの使用」を参照してください。

- (VDP)マルチテナントでは、テナントは同じ表を共有する複数のテナントをサポートする機能を持つVDPデータベースを使用します。「VPDマルチテナントの使用」を参照してください。

EclipseLinkでは、拡張可能なエンティティおよびMetadataSourceを使用した拡張可能なエンティティを介したテナントに固有の拡張も提供しています。それらの機能の詳細は、第12章「JPAエンティティおよびJAXB Beanの拡張可能化」および第13章「外部メタデータ・ソースの使用」を参照してください。

14.2 単一表マルチテナントの使用

単一表マルチテナントでは、エンティティまたはマップ済のスーパークラスがマップされるすべての表(TableまたはSecondaryTable)に、複数のテナント用の行を含めることができます。テナントに固有の行へのアクセスは、指定のテナントに制限されています。

テナント固有の行は、1つ以上のテナント識別子列を使用してテナントに関連付られています。識別子列には、どのような永続性コンテンツがアクセスできるか制限するアプリケーション・コンテキスト値が使用されています。

マップした表に対する問合せの結果は、プロパティ値として提供されたテナントの識別子の値に制限されます。これは、表でのすべてのinsert、updateおよびdelete操作に該当します。マルチテナントのメタデータがマップ済のスーパークラス・レベルで適用されると、独自のマルチテナント・メタデータを指定しないかぎり、すべてのサブエンティティに適用されます。

注意:

単一表マルチテナントのコンテキストで、単一表は、複数のテナントが1つの表を共有し、各テナントのデータは識別子列で他のテナントのデータから区別されていることを意味します。単一表マルチテナントでは、複数の表を使用することも可能ですが、その場合は、エンティティの永続性データは複数の表に保存され、複数のテナントはすべての表を共有できます。

14.2.1 単一表マルチテナントを使用する場合の主なタスク

単一表マルチテナントを使用する場合には、次のテスクを実行します。

- タスク1: 前提条件

- タスク2: 単一表マルチテナントの有効化

- タスク3: テナント識別子列の指定

- タスク4: 操作および問合せの実行

- タスク5: 継承階層での単一表マルチテナントの使用

14.2.1.1 タスク1: 前提条件

単一表マルチテナントを実装するには、次が必要です。

- TopLink 12cリリース1 (12.1.2)以上。
http://www.oracle.com/technetwork/middleware/toplink/downloads/index.htmlからTopLinkをダウンロードします。

- Oracle Database、Oracle Database Express Edition (Oracle Database XE)またはMySQLを含む対応するすべてのJava Database Connectivity (JDBC)データベース。ここで説明する手順は、Oracle Database XE 11gリリース2のものです。
保証マトリックスについては、http://www.oracle.com/technetwork/middleware/ias/index-099524.htmlを参照してください。

14.2.1.2 タスク2: 単一表マルチテナントの有効化

単一表マルチテナントは、@Multitenant注釈を使用するか、オブジェクト・リレーショナル・マッピング(ORM) XMLファイルで<multitenant>要素を使用するか、注釈とXMLの両方を使用して、宣言することにより有効にできます。

14.2.1.2.1 @Multitenant注釈の使用

@Multitenant注釈を使用する場合、@Entityまたは@MappedSuperclass注釈に含めます。次に例を示します。

@Entity
@Table(name=“EMP”)
@Multitenant(SINGLE_TABLE)
public class Employee {
}

注意:

単一表はマルチテナントのデフォルトのタイプなので、SINGLE_TABLEを@Multitenantに含める必要はありません。

注意:

識別子列はプライマリ表にあることが前提となっているので@Tableの注釈は不要です。ただし、セカンダリ表に識別子列を定義している場合、その表を@SecondaryTableを使用して識別する必要があります。

14.2.1.2.2 <multitenant>要素の使用

<multitenant>要素を使用する場合は、<entity>要素内にこの要素を指定します。次に例を示します。

<entity class="model.Employee">
<multitenant type="SINGLE_TABLE">
...
</multitenant>
...
</entity>

14.2.1.3 タスク3: テナント識別子列の指定

識別子列は、関連付けられているアプリケーション・コンテキストとともに使用して、表のどの行にアプリケーション・テナントがアクセスできるかを示します。

テナント識別子列は、@TenantDiscriminatorColumn注釈を指定するか、オブジェクト・リレーショナル(ORM) XMLファイルで<tenant-discriminator-column>要素を使用して、宣言することにより指定できます。

識別子列には、次の特徴があります。

- テナントの識別子列を使用する場合、常に@Multitenant (またはORM XMLファイルで<multitenant>)も使用する必要があります。テナント識別子列のみの指定はできません。

- テナント識別子列は、別の表が明示的に指定されている場合を除きプライマリ表上にあることが前提となっています。

- 永続性では、テナント識別子列の値はそれに関連付られているコンテンツのプロパティから移入されます。

- マルチテナント・エンティティが指定されている場合、テナント識別子列はデフォルトのものとなります。デフォルト値は次のとおりです。

- Name = TENANT_ID (データベースの列名)

- Context property = eclipselink.tenant.id (データベース列の移入に使用されるコンテキスト・プロパティ)

- テナント識別子列はアプリケーションで定義できます。つまり、各共有エンティティ表で、識別子列は特定の列には関連付られていません。TENANT_IDやT_IDなどを使用できます。

- アプリケーションで定義できるテナント識別子列の数には制限はありません。

- 識別子列には、任意の名前を使用できます。

- 生成されるスキーマには、指定したテナント識別子列などが含まれます。

- テナント識別子列は、マッピングすることもマッピング解除することもできます。

- テナント識別子列がマップされたら、関連付られているマッピング属性は読取り専用としてマークする必要があります。

- マップおよびマップ解除されている両方のプロパティは、SELECT問合せの発行時に追加の基準を形成するために使用します。

14.2.1.3.1 @TenantDiscriminatorColumn注釈の使用

@TenantDiscriminatorColumn注釈を使用する場合、エンティティまたはマップ済のスーパークラスの@Multitenant注釈に追加して、オプションでnameおよびcontextProperty属性を含めます。これらの属性を指定しない場合、デフォルトのname = "TENANT-ID"およびcontextProperty = "eclipselink.tenant-id"が使用されます。

次に例を示します。

@Entity
@Multitenant(SINGLE_TABLE)
@TenantDiscriminatorColumn(name = "TENANT", contextProperty = "multitenant.id")
public class Employee {
}

複数のテナント識別子列を指定するには、@TenantDiscriminatorColumns注釈内に複数の@TenantDiscriminatorColumn注釈を含め、プライマリ表にない場合は、列のある表を含めます。次に例を示します。

@Entity
@Table(name = "EMPLOYEE")
@SecondaryTable(name = "RESPONSIBILITIES")
@Multitenant(SINGLE_TABLE)
@TenantDiscriminatorColumns({
@TenantDiscriminatorColumn(name = "TENANT_ID",
contextProperty = "employee-tenant.id", length = 20)
@TenantDiscriminatorColumn(name = "TENANT_CODE",
contextProperty = "employee-tenant.code", discriminatorType = STRING,
table = "RESPONSIBILITIES")
}
)
public Employee() {
...
}

14.2.1.3.2 <tenant-discriminator-column>要素の使用

<tenant-discriminator-column>要素を使用する場合は、<multitenant>要素内にこの要素を指定して、オプションでnameおよびcontext-property属性を指定します。これらの属性を指定しない場合、デフォルトのname = "TENANT-ID"およびcontextProperty = "eclipselink.tenant-id"が使用されます。

次に例を示します。

<entity class="model.Employee">
<multitenant>
<tenant-discriminator-column name="TENANT"
context-property="multitenant.id"/>
</multitenant>
...
</entity>

複数の列を指定する場合は、追加の<tenant-discriminator-column>要素を指定して、プライマリ表に列がない場合は、列がある表を指定します。次に例を示します。

<entity class="model.Employee">
<multitenant type="SINGLE_TABLE">
<tenant-discriminator-column name="TENANT_ID"
context-property="employee-tenant.id" length="20"/>
<tenant-discriminator-column name="TENANT_CODE"
context-property="employee-tenant.id" discriminator-type="STRING"
table="RESPONSIBILITIES"/>
</multitenant>
<table name="EMPLOYEE"/>
<secondary-table name="RESPONSIBILITIES"/>
...
</entity>

14.2.1.3.3 テナント識別子列のマッピング

テナント識別子列は、主キーまたは別の列にマッピングできます。次の例では、DDL生成時に、表の主キーにテナント識別子列をマッピングしています。

@Entity
@Table(name = "ADDRESS")
@Multitenant
@TenantDiscriminatorColumn(name = "TENANT", contextProperty = "tenant.id",
primaryKey = true)
public Address() {
...
}

次の例では、ORM XMLファイルを使用してテナント識別子列を主キーにマップしています。

<entity class="model.Address">
<multitenant>
<tenant-discriminator-column name="TENANT"
context-property="multitenant.id" primary-key="true"/>
</multitenant>
<table name="ADDRESS"/>
...
</entity>

次の例では、テナント識別子列をAGEという別の列にマップしています。

@Entity
@Table(name = "Player")
@Multitenant
@TenantDiscriminatorColumn(name = "AGE", contextProperty = "tenant.age")
public Player() {
...

@Basic
@Column(name="AGE", insertable="false", updatable="false")
public int age;
}

次の例では、ORM XMLファイルを使用し、テナント識別子列をAGEという名前の別の列にマップしています。

<entity class="model.Player">
<multitenant>
<tenant-discriminator-column name="AGE" context-property="tenant.age"/>
</multitenant>
<table name="PLAYER"/>
...
<attributes>
<basic name="age" insertable="false" updatable="false">
<column name="AGE"/>
</basic>
...
</attributes>
...
</entity>

14.2.1.3.4 永続性ユニットおよびエンティティ・マッピングのデフォルトの定義

識別子列は、エンティティおよびマップ済スーパークラス・レベルのみでなく、persistence-unit-defaultsおよびentity-mappingsレベルで構成してデフォルトとすることができます。これらのレベルでメタデータを定義する場合、同様なJPAのメタデータのデフォルト設定およびオーバーラード・ルールに従います。

デフォルトのテナント識別子列メタデータは、ORM XMLファイルのpersistence-unit-defaultsレベルで指定します。このレベルで定義すると、SINGLE_TABLEのマルチテナント・タイプが指定された永続性ユニットのすべてのエンティティにデフォルトが適用されます(独自のテナント識別子メタデータが指定されているものは除きます)。次に例を示します。

<persistence-unit-metadata>
<persistence-unit-defaults>
<tenant-discriminator-column name="TENANT_ID" context-property="tenant.id"/>
</persistence-unit-defaults>
</persistence-unit-metadata>

テナント識別子列メタデータは、ORM XMLファイルのentity-mappingsレベルで指定することも可能です。このレベルで定義すると、永続性ユニットのデフォルトがオーバーライドされ、マッピング・ファイルでマルチテナント・タイプにSINGLE_TABLEと指定されたすべてのエンティティにそれが適用されます(独自のテナント識別子メタデータが指定されているものは除きます)。次に例を示します。

<entity-mappings>
...
...
<tenant-discriminator-column name="TENANT_ID" context-property="tenant.id"/>
...
</entity-mappings>

14.2.1.4 コンテキスト・プロパティおよびキャッシュ範囲の構成

ランタイム・コンテキスト・プロパティは、マルチテナント戦略を実装するためにエンティティ(またはマップ済スーパークラス)のマルチテナント構成とともに使用されます。たとえば、テナント識別子列に割り当てられたエンティティ用のテナントIDは、実行時に、テナントが行およびデータベース表を所有しているか(またはアクセス)に応じて、(エンティティ・マネージャを介して)データにアクセスする際、制限を行うために使用されます。

マルチテナント・プロパティは、実行時に永続性ユニットの定義に指定するか、エンティティ・マネージャ・ファクトリ・コールの生成に渡すことができます。

テナント識別子列の優先順位は次のとおりです。

1. EntityManager

2. EntityManagerFactory

3. アプリケーション・コンテキスト(Java EEコンテナにある場合)

たとえば、persistence.xmlの永続性ユニットで構成を設定するには次を実行します。

<persistence-unit name="multitenant">
...
<properties>
<property name="tenant.id" value="707"/>
...
</properties>
</persistence-unit>

または、プログラミングを行いプロパティを設定するには、次を実行します。

HashMap properties = new HashMap();
properties.put("tenant.id", "707");
...
EntityManager em = Persistence.createEntityManagerFactory("multi-tenant",
properties).createEntityManager();

注意:

ライブEntityManager時にテナントIDを切り替えることは許可されていません。

14.2.1.4.1 共有エンティティ・マネージャの構成

デフォルトで、テナントはエンティティ・マネージャ・ファクトリを共有しています。単一のアプリケーション・インスタンスで永続性ユニットのEntityManagerFactoryが共有されている場合、複数のテナントのリクエストを処理できます。

次の例では、エンティティ・マネージャ・ファクトリが共有されている場合の構成を示します。

EntityManager em = createEntityManager(MULTI_TENANT_PU);
em.getTransaction().begin();
em.setProperty(EntityManagerProperties.MULTITENANT_PROPERTY_DEFAULT, "my_id");

共有エンティティ・マネージャ・ファクトリを使用する際、デフォルトではL2キャッシュは共有されず、従ってマルチテナント・エンティティのキャッシュ設定はISOLATEDとなります。

キャッシュを共有するには、eclipselink.multitenant.tenants-share-cacheプロパティをtrueに設定します。これにより、マルチテナント・エンティティのキャッシュ設定は、PROTECTEDになります。

注意:

PROTECTEDの設定を使用している場合、キャッシュを使用する問合せは他のテナントのデータを返す場合があります。

14.2.1.4.2 非共有エンティティ・マネージャの構成

共有されないエンティティ・マネージャ・ファクトリを作成する場合、eclipselink.multitenant.tenants-share-emfプロパティはfalseに設定します。

エンティティ・マネージャ・ファクトリが共有されない場合、eclipselink.session-nameプロパティを使用し、次の例のようにセッション名を一意に指定する必要があります。これにより、テナントごとに一意のサーバー・セッションおよびキャッシュが提供されます。これにより、完全なキャッシュ機能が提供されます。次に例を示します。

HashMap properties = new HashMap();
properties.put("tenant.id", "707");
properties.put("eclipselink.session-name", "multi-tenant-707");
...
EntityManager em = Persistence.createEntityManagerFactory("multitenant",
properties).createEntityManager();

もう1つ例を示します。

HashMap properties = new HashMap();
properties.put(PersistenceUnitProperties.MULTITENANT_SHARED_EMF, "false");
properties.put(PersistenceUnitProperties.SESSION_NAME, "non-shared-emf-for-this-emp");
properties.put(PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT, "this-emp");
...
EntityManager em = Persistence.createEntityManagerFactory("multi-tenant-pu", properties).createEntityManager();

永続性ユニットの定義の例を示します。

<persistence-unit name="multi-tenant-pu">
...
<properties>
<property name="eclipselink.multitenant.tenants-share-emf" value="false"/>
<property name="eclipselink.session-name"
value="non-shared-emf-for-this-emp"/>
<property name="eclipselink.tenant-id" value="this-emp"/>
...
</properties>
</persistence-unit>

14.2.1.4.3 エンティティ・マネージャの構成

エンティティ・マネージャ・レベルでプロパティを構成する際、テナントごとに同じサーバー・セッションを使用できるようキャッシュ戦略を指定する必要があります。たとえば、L2キャッシュに共有されているテナント情報がないようにするには、分離レベル(L1キャッシュ)を設定します。この設定は、エンティティ・マネージャ・ファクトリの作成時に設定されます。

HashMap tenantProperties = new HashMap();
properties.put("tenant.id", "707");

HashMap cacheProperties = new HashMap();
properties.put("eclipselink.cache.shared.Employee", "false");
properties.put("eclipselink.cache.size.Address", "10");
properties.put("eclipselink.cache.type.Contract", "NONE");
...
EntityManager em = Persistence.createEntityManagerFactory("multitenant",
cacheProperties).createEntityManager(tenantProperties);
...

14.2.1.5 タスク4: 操作および問合せの実行

テナント識別子列はエンティティ・マネージャの操作時および問合せ時に使用されます。テナント識別子列と値は、次のエンティティ・マネージャの操作でサポートされます。

- persist()

- find()

- refresh()

テナント識別子列と値は、次のエンティティ・マネージャの問合せでサポートされます。

- 名前付き問合せ

- すべて更新

- すべて削除

注意:

マルチテナントは、名前付きのネイティブ問合せではサポートされません。マルチテナント環境で名前付きのネイティブ問合せを使用する場合は、マルチテナントに関する問題を問合せで直接に手動で処理してください。一般に、マルチテナント環境では名前付きのネイティブ問合せを使用しないことをお薦めします。

14.2.1.6 タスク5: 継承階層での単一表マルチテナントの使用

継承戦略は、継承タイプ(@javax.persistence.Inheritance)を指定して構成します。単一表マルチテナントは、次のように継承階層で使用できます。

- SINGLE_TABLEまたはJOINED継承戦略の使用時には、マルチテナントのメタデータは、継承階層のルート・レベルでのみ適用できます。

- TABLE_PER_CLASS継承階層でマルチテナントのメタデータを指定することも可能です。この場合、各エンティティはすべてのマッピング・データを含む独自の表を持つことになります(SINGLE_TABLEまたはJOINED戦略の場合は異なります)。その結果、TABLE_PER_CLASS戦略では、階層内の一部のエンティティがマルチテナントとなり、他はそうでなくなる場合があります。そのタイプのみを構築するためエンティティを単一の表に分離できないため、もう1つの継承戦略では、ルート・レベルでしかマルチテナントを指定できません。

14.3 テナントごとの表マルチテナントの使用

テナントごとの表マルチテナントでは、テナント独自の1つ以上の表に、アプリケーションの複数のテナントはデータを分離できます。複数のテナントの表は、名前に接頭辞または接尾辞が使用して区別して共有スキーマに含めるか、テナント固有の別のスキーマに含めることができます。テナントごとの表エンティティは、同じ永続性ユニットに他のタイプのマルチテナント・エンティティと混在させることができます。

テナントごとの表マルチテナント・タイプは次とともに使用します。

- 識別子の種類を指定するテナント表識別子(接頭辞または接尾辞付きのスキーマまたは名前)

- ユーザーを識別するテナントID(永続性ユニットごとにテナントごとの表を分離する場合、エンティティ・マネージャごとに構成するか、エンティティ・マネージャ・ファクトリで構成)

単一のアプリケーション・インスタンスで永続性ユニットのEntityManagerFactoryが共有されている場合、複数のテナントのリクエストを処理できます。

またはテナントごとに、別のEntityManagerFactoryインスタンスを使用することも可能です。(これはテナントごとに拡張を使用する場合に必要です。)この場合、テナント固有のスキーマおよび表明は、eclipselink-orm.xml構成ファイルに定義します。永続性ユニットにMetadataSourceを登録する必要があります。MetadataSourceは、アプリケーション外から提供されるその他の永続性ユニット・メタデータをサポートするために使用します。

MetadataSourceの詳細は、第13章「外部メタデータ・ソースの使用」を参照してください。『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』のmetadata-sourceも参照してください。

テナントごとの表マルチテナント・タイプでは、個々のテナント表をエンティティ・レベルで使用することができます。トランザクションの開始後、各エンティティ・マネージャでテナントのコンテキスト・プロパティを提供する必要があります。

- エンティティの表(TableおよびSecondaryTable)は、テナントのコンテキストに基づく、テナントの個別の表です。結合またはコレクション表を使用するエンティティ内のリーションシップも、テナントごとの表のコンテキスト内に存在することが前提となっています。

- マルチテナントのメタデータは、SINGLE_TABLEまたはJOINED継承戦略の使用時には、継承階層のルート・レベルでしか適用できません。マルチテナント・メタデータは、TABLE_PER_CLASS継承階層内に指定できます。

14.3.1 テナントごとの表マルチテナントを使用する場合の主なタスク

次のタスクでは、テナントごとの表マルチテナントを使用する手順を説明します。

- タスク1: 前提条件

- タスク2: テナントごとの表マルチテナントの有効化

- タスク3: テナント表識別子の指定

- タスク4: 実行時のコンテキスト・プロパティの指定

14.3.1.1 タスク1: 前提条件

テナントごとの表マルチテナントを実装して使用するには、次が必要です。

- TopLink 12cリリース1 (12.1.2)以上。
http://www.oracle.com/technetwork/middleware/toplink/downloads/index.htmlからTopLinkをダウンロードします。

- Oracle Database、Oracle Database Express Edition (Oracle Database XE)またはMySQLを含む対応するすべてのJava Database Connectivity (JDBC)データベース。ここで説明する手順は、Oracle Database XE 11gリリース2のものです。
保証マトリックスについては、http://www.oracle.com/technetwork/middleware/ias/index-099524.htmlを参照してください。

14.3.1.2 タスク2: テナントごとの表マルチテナントの有効化

テナントごとの表マルチテナントは、@Multitenant注釈を使用するか、オブジェクト・リレーショナル・マッピング(ORM) XMLファイルで<multitenant>要素を使用するか、注釈とXMLの両方を使用して、宣言することにより有効にできます。

14.3.1.2.1 @Multitenantおよび@TenantTableDiscriminator注釈の使用

@Multitenant注釈を使用する場合は、@Entityまたは@MappedSuperclass注釈とともにこの注釈を指定して、TABLE_PER_TENANT属性を指定します。

次に例を示します。

@Entity
@Multitenant(TABLE_PER_TENANT
...)
public class Employee {
}

TABLE_PER_TENANT属性は、クライアントにエンティティと関連付けられている専用の表があることを指定します(TableおよびSecondaryTable)。

14.3.1.2.2 <multitenant>要素の使用

<multitenant>要素を使用する場合は、<entity>要素内にこの要素を指定します。次に例を示します。

<entity class="model.Employee">
<multitenant type="TABLE_PER_TENANT">
...
</multitenant>
...
</entity>

14.3.1.3 タスク3: テナント表識別子の指定

テナント表識別子は、テナントごとの表マルチテナント戦略で使用する表識別子の種類を示します。テナント表識別子は、プロパティで指定します。独自の識別子を定義するか、デフォルトのorg.eclipse.persistence.config.PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT = "eclipselink.tenant-id"プロパティを使用します。

テナント表識別子はエンティティまたはマップ済のスーパークラス・レベルで指定でき、Multitenant(TABLE_PER_TENANT)の指定が常に必要です。テナント表識別子のみの指定では不十分です。

テナント表識別子は、関連付けられているアプリケーション・コンテキストとともに使用して、どの表にアプリケーション・テナントがアクセスできるかを示します。

14.3.1.3.1 @TenantTableDiscriminator注釈の使用

@TenantTableDiscriminator注釈を使用し、表とテナントの関連付けを指定します。テナント表識別子には、種類とコンテキスト・プロパティを含む必要があります。

- type属性を使用し、使用する識別子の種類を指定します。

- テナント表識別子を接頭辞としてすべてのマルチテナント表に適用するには、PREFIXを使用します。

- テナント表識別子を接尾辞としてすべてのマルチテナント表に適用するには、SUFFIXを使用します。

- テナント表識別子をスキーマとしてすべてのマルチテナント表に適用するには、SCHEMAを使用します。この戦略では、データベースを正しくプロビジョニングする必要があります。

- contextProperty属性を使用し、ユーザーを識別します。コンテキスト・プロパティの値は、ユーザーを識別するテナントIDです。これは、エンティティ・マネージャに構成するか、永続性ユニットごとにテナントごとの表を分離する場合は、エンティティ・マネージャ・ファクトリに構成します。

次に例を示します。

@Entity
@Table(name=“EMP”)
@Multitenant(TABLE_PER_TENANT)
@TenantTableDiscriminator(type=SCHEMA, contextProperty="eclipselink-tenant.id")
public class Employee {
...
}

14.3.1.3.2 <tenant-table-discriminator>要素の使用

<tenant-table-discriminator>要素を使用する場合は、<multitenant>要素内にこの要素を指定して、nameおよびcontext-property属性を指定します。次に例を示します。

<entity class="Employee">
<multitenant type="TABLE_PER_TENANT">
<tenant-table-discriminator type="SCHEMA"
context-property="eclipselink-tenant.id"/>
</multitenant>
<table name="EMP">
...
</entity>

14.3.1.4 タスク4: 実行時のコンテキスト・プロパティの指定

実行時に、エンティティ・マネージャ・ファクトリに渡される永続性ユニットの定義を使用するコンテキスト・プロパティを指定するか、個々にエンティティ・マネージャに設定して、コンテキスト・プロパティ構成を指定できます。次に例を示します。

<persistence-unit name="multitenant">
...
<properties>
<property name="tenant.id" value="707"/>
...
</properties>
</persistence-unit>

プログラミングを行い、実行時にコンテキスト・プロパティを指定する手順は次のとおりです。

HashMap properties = new HashMap();
properties.put(PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT, "707");
EntityManager em = Persistence.createEntityManagerFactory("multitenant-pu",
properties).createEntityManager();

エンティティ・マネージャのプロパティ定義は、次のとおりです。

EntityManager em =
Persistence.createEntityManagerFactory("multitenant-pu").createEntityManager();
em.beginTransaction();
em.setProperty("other.tenant.id.property", "707");
em.setProperty(EntityManagerProperties.MULTITENANT_PROPERTY_DEFAULT, "707");
...

14.3.1.5 タスク5: 操作および問合せの実行

テナント識別子列はエンティティ・マネージャの操作時および問合せ時に使用されます。テナント識別子列と値は、次のエンティティ・マネージャの操作でサポートされます。

- persist()

- find()

- refresh()

テナント識別子列と値は、次のエンティティ・マネージャの問合せでサポートされます。

- 名前付き問合せ

- すべて更新

- すべて削除

注意:

マルチテナントは、名前付きのネイティブ問合せではサポートされません。マルチテナント環境で名前付きのネイティブ問合せを使用する場合は、マルチテナントに関する問題を問合せで直接に手動で処理してください。一般に、マルチテナント環境では名前付きのネイティブ問合せを使用しないことをお薦めします。

14.4 VPDマルチテナントの使用

仮想プライベート・データベース(VPD)では、様々なパラメータに基づくセキュリティ・コントロールを使用して、データベース・オブジェクトへのアクセスを制限します。

たとえば、Oracle仮想プライベート・データベースでは、行および列レベルでデータベースへのアクセスを制限するセキュリティ・ポリシーをサポートしています。セキュリティ・ポリシーが適用された表、ビュー、シノニムに対して発行されたSQL文に対し、Oracle VPDでは、動的なWHERE句を追加します。

Oracle仮想プライベート・データベースでは、データベース表、ビューまたはシノニムに対し、セキュリティが直接強制されます。セキュリティ・ポリシーはこれらのデータベース・オブジェクトに直接付加され、ユーザーがデータにアクセスするたびにポリシーは自動的に適用されるため、セキュリティは回避できません。

ユーザーがOracle仮想プライベート・データベース・ポリシーで保護されている表、ビューまたはシノニムに直接的または間接的にアクセスすると、Oracle DatabaseはユーザーのSQL文を動的に変更します。この変更は、セキュリティ・ポリシーを実装する関数によって戻されたWHERE条件(述語)に基づいて行われます。Oracle仮想プライベート・データベースでは、関数内に記述された条件、または関数が戻す条件を使用して、動的に、またユーザーに対して透過的に文を変更します。Oracle仮想プライベート・データベースのポリシーは、SELECT、INSERT、UPDATE、INDEXおよびDELETE文に適用できます。

EclipseLink VPDマルチテナントを使用する場合、データベースでは、SELECT、INSERT、UPDATE、INDEXおよびDELETEのすべての問合せでテナント・フィルタリングを行います。

EclipseLink VPDマルチテナントを使用するには、@Multitenantおよび@TenantDiscriminatorColumnを使用した次の例のとおり、まずデータベースでVPDを構成し、その後エンティティまたはマップ済のスーパークラスでマルチテナントを指定する必要があります。

14.4.1 VPDマルチテナントを使用する場合の主なタスク

次のタスクでは、Oracle仮想プライベート・データベースでVPDマルチテナントを使用する手順を説明します。

- タスク1: 前提条件

- タスク2: 仮想プライベート・データベースの構成

- タスク3: エンティティまたはマップ済スーパークラスの構成

- タスク4: 基準生成の無効化

- タスク5: persistence.xmlの構成

14.4.1.1 タスク1: 前提条件

VPDマルチテナントを実装し使用するには、次が必要です。

- TopLink 12cリリース1 (12.1.2)以上。
http://www.oracle.com/technetwork/middleware/toplink/downloads/index.htmlからTopLinkをダウンロードします。

- Oracle仮想プライベート・データベースなど、すべての対応するVDPをサポートするJava Database Connectivity (JDBC)データベース。
保証マトリックスについては、http://www.oracle.com/technetwork/middleware/ias/index-099524.htmlを参照してください。

14.4.1.2 タスク2: 仮想プライベート・データベースの構成

この例では、Oracle仮想プライベート・データベースはポリシーとストアド・プロシージャで構成されています。ポリシーとは、問合せの結果を制限するストアド関数を使用するよう、データベースに通知するデータベース・コールです。この例の関数は、ident_funcといい、SCOTT.TASK表に対してSELECT、UPDATEまたはDELETEが実行されると常に実行されます。ポリシーは次のように生成します。

CALL DBMS_RLS.ADD_POLICY ('SCOTT', 'TASK', 'todo_list_policy', 'SCOTT', 'ident_func', 'select, update, delete'));

次で定義する関数は、VPDが接続に渡される識別子に基づいてデータを制限するために使用されます。この関数では、表のUSER_ID列を使用して行を制限しています。行は、userenvコンテキストのclient_identifier変数に何が設定されているかに基づいて制限されます。

CREATE OR REPLACE FUNCTION ident_func (p_schema IN VARCHAR2 DEFAULT NULL, p_object IN VARCHAR2 DEFAULT NULL)
RETURN VARCHAR2
AS
BEGIN
RETURN 'USER_ID = sys_context(''userenv'', ''client_identifier'')';
END;

14.4.1.3 タスク3: エンティティまたはマップ済スーパークラスの構成

前述のとおり、VPDは行へのアクセスを制限するためにUSER_ID列を使用するよう構成されています。したがって、挿入時には、EclipseLinkにUSER_ID列を自動移入するよう通知する必要があります。次のコードでは、EclipseLinkのマルチテナントが使用され、tenant.idというプロパティを使用して、エンティティ・マネージャにクライアント識別子が渡されることが指定されています。フィルタリングはVPDがデータベースに対して行うので、このエンティティでキャッシュを無効にしてユーザー間でリークが発生するのを避ける必要があります。

@Entity
@Multitenant(VPD)
@TenantDiscriminatorColumn(name = "USER_ID", contextProperty = "tenant.id")
@Cacheable(false)

public class Task implements Serializable {
...
...

14.4.1.4 タスク4: 基準生成の無効化

単一表およびテナントごとの表マルチテナントが有効な場合、生成されるすべてのSQLにクライアント識別子が自動的に付加されます。ただし、VPDを使用してデータへのアクセスを制限する場合は、識別子が自動的に付加されないようにする必要があります。

TopLink 12cリリース1 (12.1.2)以上では、次のように基準の生成を無効にします。

14.4.1.5 タスク5: persistence.xmlの構成

persistence.xmlに次のプロパティを追加します。

次を含め、VPD識別子を設定およびクリアします。

<property name="eclipselink.session-event-listener" value="example.VPDSessionEventAdapter" />

次を含め、エンティティ・マネージャごとに接続を1つ用意します。

<property name="eclipselink.jdbc.exclusive-connection.mode" value="Always" />

次を含め、EclipseLinkからネイティブ問合せを実行できるようにします。これは、VPDアーチファクトの生成に必要です。

<property name="eclipselink.jdbc.allow-native-sql-queries" value="true" />
</properties>

次に例を示します。

<properties>
<property name="eclipselink.session-event-listener" value="example.VPDSessionEventAdapter" />
<property name="eclipselink.jdbc.exclusive-connection.mode" value="Always" />
<property name="eclipselink.jdbc.allow-native-sql-queries" value="true" />
...
</properties>

14.5 その他の参考資料

この章のソリューションが実装されているその他のテクノロジおよびツールの詳細は、次の参考資料を参照してください。

- コード例

- http://wiki.eclipse.org/EclipseLink/Examples/MySports

- 『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』で次を参照してください。

- @Multitenant

- @TenantDiscriminatorColumn

- @TenantDiscriminatorColumns

- @TenantTableDiscriminator

15 XMLへのJPAのマッピング

この章では、POJO (Plain Old Java Object)をXMLにマッピングするためのJava EE標準であるJava Architecture for XML Binding (JAXB)でJPAを使用する方法、およびJPAエンティティをXMLにマッピングするMapping Objects to XML (MOXy)拡張機能を使用する方法について説明します。XMLへのJPAエンティティのマッピングは、Java API for RESTful Web Services (JAX-RS)、Java API for XML Web Services (JAX-WS)またはSpringを使用してデータ・アクセス・サービスを作成する場合に便利です。

この章には次のトピックが含まれます:

- 15.1項「ソリューションの概要」

- 15.2項「XMLへのJPAエンティティのバインディング」

- 15.3項「XMLテキスト・ノードへの単純なJava値のマッピング」

- 15.4項「XMLメタデータ表現を使用したJAXB注釈のオーバーライド」

- 15.5項「マッピングに対するXPath述語の使用」

- 15.6項「動的JAXB/MOXyの使用」

- 15.7項「その他の参考資料」

ユース・ケース

JPAエンティティをユーザーがXMLにマップする必要があります。

解決方法

TopLinkでは、EclipseLinkのJAXBの拡張を介して、JAXB標準をサポートしています。

コンポーネント

- TopLink 12cリリース1 (12.1.2)以上。

注意:

TopLinkのコア機能は、オープン・ソースのEclipse Foundationの永続性フレームワークであるEclipseLinkによって提供されています。EclipseLinkでは、Java Persistence API (JPA)、Java Architecture for XML Binding (JAXB)、および標準に基づいたその他の永続性テクノロジと、それらの標準の拡張が実装されます。TopLinkには、EclipseLinkのすべてに加え、Oracleの追加機能が含まれています。

- XML文書

例

関連情報については、次のEclipseLinkおよびJAXBの例を参照してください。

- http://wiki.eclipse.org/EclipseLink/Examples/MOXy

- http://java.sun.com/developer/technicalArticles/WebServices/jaxb/index.html

15.1 ソリューションの概要

この章では、XMLにJPAエンティティをマッピングする一般的な方法をいくつか示します。次の例を扱うには、JAXB、MOXy、XMLバインディング、JAXB注釈のオーバーライド方法などのJPAからXMLへのマッピングの全体的な概念を理解している必要があります。次の項では、これらの概念の基礎的なことがらを説明します。

- 15.1.1項「XMLバインディングの理解」

- 15.1.2項「JAXBの理解」

- 15.1.3項「MOXyの理解」

- 15.1.4項「XMLデータ表現の理解」

15.1.1 XMLバインディングの理解

XMLバインディングとは、コンピュータのメモリーのオブジェクトとして、XML文書内に情報を表現する方法です。これにより、Domain Object Model (DOM)、Simple API for XML (SAX)またはStreaming API for XML (StAX)を使用してXML自身の直接表現からデータを取得しなくても、オブジェクトからXML内のデータにアクセスできるようになります。バインディングする際に、JAXBでは、JPAエンティティのグラフにツリー構造が適用されます。グラフの複数ツリー表現は可能で、選択されたルート・オブジェクトおよびリレーションシップがトラバースする方向に依存します。

JAXBによるXMLバインディングの例は15.2項「XMLへのJPAエンティティのバインディング」にあります。

15.1.2 JAXBの理解

JAXBは、XML文書をJava形式でJavaプログラムに提示することにより、JavaプログラムがXML文書にアクセスできようにするJava APIです。このプロセスはバインディングと呼ばれ、コンピュータ・メモリー内のオブジェクトとして、XML文書内に情報が表現されます。これにより、Domain Object Model (DOM)またはStreaming API for XML (SAX)を使用してXML自身の直接表現からデータを取得しなくても、オブジェクトからXML内のデータにアクセスできるようになります。通常、XMLバインディングをJPAエンティティとともに使用し、JAX-WSまたはJAX-RSの実装を利用して、データ・アクセス・サービスを作成します。これら両方のWebサービス標準では、JAXBがデフォルトのバインディング・レイヤーとして使用されています。このサービスにより、クライアント・コンピュータでJavaが使用されている場合とそうでない場合がある複数のコンピュータ間で、JPAによって公開されたデータにアクセスできるようになります。

JAXBでは、注釈の拡張セットを使用して、JavaからXMLへのマッピングのバインディング・ルールを定義します。これらの注釈は、EclipseLink APIのjavax.xml.bind.*パッケージのサブクラスになっています。これらの注釈の詳細は、『Oracle TopLink Java APIリファレンス』を参照してください。

JAXBの詳細は、次の『Java Architecture for XML Binding (JAXB)』を参照してください。

http://www.eclipse.org/eclipselink/moxy.php

15.1.3 MOXyの理解

MOXyはEclipseLinkにおけるJAXBの実装です。これにより、POJOモデルをXMLスキーマにマップできるようになるので、JPAからXMLへのマッピングを作成する能力が大幅に拡張します。MOXyでは、javax.xml.bind.annotationのすべての標準JAXB注釈のサポートに加えて、org.eclipse.persistence.oxm.annotationsパッケージの独自の拡張機能も提供されています。これら後者の注釈を標準の注釈とともに使用すれば、JAXBの実用性をさらに拡張できます。MOXyは最適化されたJAXB実装なので、拡張機能を明示的に使用してもしなくても実装できます。MOXyには、次の利点があります。

- 独自のクラスを独自のXMLスキーマにマップできるようになります。このプロセスを「中間突合せマッピング」と呼びます。これにより、マップされたクラスを1つのXMLスキーマに静的にカップリングしなくてすみます。

- Xpathベースのマッピング、JSONバインディング、複合キー・マッピングやバックポインタとのリレーションシップのマッピングなど、JPAからXMLへのマッピングの重要な問題に対処するための固有の機能が用意されています。

- 既存のJPAモデルを業界標準のスキーマにマップできます。

- MOXyマッピングとEclipseLinkの永続性フレームワークを組合せ、JCA経由でデータを対話的に処理できます。

- 数種類のシナリオで優れたパフォーマンスが得られます。

MOXyの詳細は、次の場所にあるMOXyのFAQを参照してください。

http://wiki.eclipse.org/EclipseLink/FAQ/WhatIsMOXy

15.1.4 XMLデータ表現の理解

JPAからXMLへのマッピングに注釈を使用することは、常に最も効果的とはかぎりません。たとえば、次の場合にはJAXBを使用しません。

- サード・パーティのクラスにメタデータを指定する必要があるが、ソースにアクセスできない場合。

- 複数のXMLスキーマにオブジェクト・モデルをマップする必要がある場合。JAXBのルールでは、注釈を使用して複数のマッピングを適用することはできません。

- オブジェクト・モデルにすでに多くの注釈(たとえば、JPA、Spring、JSR-303などのサービスから)が含まれていて、他の場所でメタデータを指定する必要がある場合。

これらの状況および類似の状況では、eclipselink_oxm.xmlファイルを公開して、XMLデータ表現を使用できます。

XMLメタデータは、次の2つのモードで動作します。

- 注釈で指定されたメタデータに追加します。これは、次の場合に便利です。

- XML表現のバージョンのひとつが注釈に定義されており、XMLメタデータを使用して将来のバージョンのメタデータを微調整する場合。

- 標準のJAXB注釈を使用し、かつMOXy拡張機能用のXMLメタデータを使用する場合。このようにすると、コンパイル時の依存関係がオブジェクト・モデルに新たに生じることはありません。

- 注釈メタデータを完全に置換します。これは、様々なXML表現にマップする必要がある場合に便利です。

XMLデータ表現の使用方法の詳細は、15.4項「XMLメタデータ表現を使用したJAXB注釈のオーバーライド」を参照してください。

15.2 XMLへのJPAエンティティのバインディング

次の例は、JAXB注釈を使用してJPAエンティティをXMLにバインドする方法を示しています。バインディングの詳細は、15.1.1項「XMLバインディングの理解」を参照し、JAXBの詳細は、15.1.2項「JAXBの理解」を参照してください。

- 15.2.1項「XMLへのJPAリレーションシップのバインディング」

- 15.2.2項「XMLへの複合主キーのバインディング」

- 15.2.3項「XMLへの埋込みIDクラスのバインディング」

15.2.1 XMLへのJPAリレーションシップのバインディング

次の演習問題は、JAXBを使用して一連のJPAエンティティからXML表現を導出する方法を示しています。このプロセスは「バインディング」と呼ばれます(XMLバインディングの詳細は、15.2項「XMLへのJPAエンティティのバインディング」を参照してください)。これらの例は、次の2つの一般的なJPAリレーションシップをバインドする方法を示しています。

- 私有のリレーションシップ

- 共有参照のリレーションシップ

従業員エンティティを、その従業員の電話番号、住所および部門にマッピングしています。

15.2.1.1 タスク1: アクセッサ・タイプの定義およびクラスのインポート

次のすべての例で、同じアクセッサ・タイプFIELDを使用しているので、JAXB注釈@XmlAccessorTypeを使用してパッケージ・レベルでアクセッサ・タイプを定義します。この時点で、必要なクラスもインポートします。

@XmlAccessorType(XmlAccessType.FIELD)
package com.example.model;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;

15.2.1.2 タスク2: 私有のリレーションシップのマッピング

「私有」のリレーションシップは、ターゲット・オブジェクトが1つのソース・オブジェクトのみによって参照されている場合に発生します。このタイプのリレーションシップは、1対1および埋込み、または1対多のどちらの場合にも可能です。

このタスクでは、Employeeエンティティと、AddressおよびPhoneNumberエンティティの間のこれら両方のタイプのリレーションシップに対して双方向のマッピングを作成する方法を示します。

15.2.1.2.1 1対1および埋込みのリレーションシップのマッピング

JPAの@OneToOneおよび@Embedded注釈は、ソース・エンティティの1つのインスタンスのみが、同じターゲット・エンティティ・インスタンスを参照できることを示しています。この例は、EmployeeエンティティをAddressエンティティにマップする方法、およびその逆にマップする方法を示しています。従業員は1つの住所のみに関連付けられるので、1対1マッピングと見なされます。このリレーションシップは双方向、つまりEmployeeはEmployee側からも指している必要のあるAddressを指すので、バックポインタにはEclipseLinkの拡張機能@XmlInverseReferenceが使用されています。

1対1および埋込みマッピングを作成するには:

1. 15.2.1.1項「タスク1: アクセッサ・タイプの定義およびクラスのインポート」の説明に従って、アクセッサ・タイプFIELDがパッケージ・レベルで定義されていることを確認します。

2. @OneToOne注釈をEmployeeエンティティに挿入することにより、リレーションシップの1方向(この場合は、Addressのemployeeプロパティ)をマップします。

@OneToOne(mappedBy="resident")
private Address residence;

mappedBy引数は、リレーションシップがresidentフィールドによって所有されていることを示します。

3. @OneToOneおよび@XmlInverseMapping注釈をAddressエンティティに挿入することにより、戻り方向(この場合は、Employeeのaddressプロパティ)をマップします。

@OneToOne
@JoinColumn(name="E_ID")
@XmlInverseReference(mappedBy="residence")
private Employee resident;

mappedByフィールドは、このリレーションシップがresidenceフィールドによって所有されていることを示します。@JoinColumnは、外部キーが格納される列を示します。

エンティティは、例15-1および例15-2に示すエンティティと同じように指定してください。

15.2.1.2.2 1対多のリレーションシップのマッピング

JPAの@OneToMany注釈は、ソース・エンティティの1つのインスタンスが同じターゲット・エンティティの複数のエンティティを参照できることを示しています。たとえば、1人の従業員に、固定電話、携帯電話、連絡先の電話、勤務先の予備の電話番号など、複数の電話番号がある場合があります。異なる各番号がPhoneNumberエンティティのインスタンスになり、1つのEmployeeエンティティが各インスタンスを指す場合があります。

このタスクでは、従業員をその従業員の電話番号の1つにマッピングして、逆方向にもマッピングします。EmployeeとPhoneNumberのリレーションシップは双方向なので、この例でも、EclipseLinkの拡張機能@XmlInverseReferenceを使用してバックポインタをマップします。

1対多マッピングを作成するには、次のようにします。

1. 15.2.1.1項「タスク1: アクセッサ・タイプの定義およびクラスのインポート」の説明に従って、アクセッサ・タイプFIELDがパッケージ・レベルで定義されていることを確認します。

2. @OneToMany注釈をEmployeeエンティティに挿入することにより、リレーションシップの1方向(この場合は、PhoneNumberのemployeeプロパティ)をマップします。

@OneToMany(mappedBy="contact")
private List<PhoneNumber> contactNumber;

mappedByフィールドは、このリレーションシップがcontactフィールドによって所有されていることを示します。

3. @ManyToOneおよび@XmlInverseMapping注釈をPhoneNumberエンティティに挿入することにより、戻り方向(この場合は、Employeeのphone numberプロパティ)をマップします。

@ManyToOne
@JoinColumn(name="E_ID", referencedColumnName = "E_ID")
@XmlInverseReference(mappedBy="contactNumber")
private Employee contact;

mappedByフィールドは、このリレーションシップがcontactNumberフィールドによって所有されていることを示します。@JoinColumnは、外部キーが格納される列(name="E_ID")および外部キーによって参照される列(referencedColumnName = "E_ID")を示しています。

エンティティは、例15-1および例15-3に示すエンティティと同じように指定してください。

15.2.1.3 タスク3: 共有参照リレーションシップのマッピング

共有参照リレーションシップは、ターゲット・オブジェクトが複数のソース・オブジェクトによって参照されている場合に発生します。たとえば、IT、人事、財務などの複数の部門にビジネスが区分されている場合があります。これらの各部門には、職責、賃金水準、勤務先などの異なる複数の従業員がいます。部門および従業員を管理するには、共有参照リレーションシップが必要になります。

XMLのネストを使用して共有参照リレーションシップを安全に表現することはできないので、キー・リレーションシップを使用します。JPAエンティティのIDフィールドを利用するには、EclipseLinkのJAXB @XmlID注釈を文字列以外のフィールドとプロパティに、@XmlIDREFを文字列のフィールドとプロパティに使用する必要があります。

この項では、多対1の共有参照リレーションシップおよび多対多の共有参照リレーションシップのマップ方法を示す例を示します。

15.2.1.3.1 多対1の共有参照リレーションシップのマッピング

多対1のマッピングでは、ソース・エンティティの1つ以上のインスタンスが同じターゲット・エンティティのインスタンスを参照できます。この例は、従業員の複数の電話番号のいずれか1つに従業員をマップする方法を示しています。

多対1の共有参照リレーションシップをマップするには:

1. 15.2.1.1項「タスク1: アクセッサ・タイプの定義およびクラスのインポート」の説明に従って、アクセッサ・タイプFIELDがパッケージ・レベルで定義されていることを確認します。

2. @ManyToOne注釈をPhoneNumberエンティティに挿入することにより、リレーションシップの1方向(この場合は、Employeeのphone numberプロパティ)をマップします。

@ManyToOne
@JoinColumn(name="E_ID", referencedColumnName = "E_ID")
@XmlIDREF
private Employee contact;

@JoinColumnは、外部キーが格納される列(name="E_ID")および外部キーによって参照される列(referencedColumnName = "E_ID")を示しています。@XmlIDREF注釈は、これが、対応する表の主キーになることを示しています。

3. @OneToManyおよび@XmlInverseMapping注釈をAddressエンティティに挿入することにより、戻り方向(この場合は、PhoneNumberのemployeeプロパティ)をマップします。

@OneToMany(mappedBy="contact")
@XmlInverseReference(mappedBy="contact")
private List<PhoneNumber> contactNumber;

両方の注釈のmappedByフィールドは、このリレーションシップがcontactフィールドによって所有されていることを示しています。

エンティティは、例15-1および例15-3に示すエンティティと同じように指定してください。

15.2.1.3.2 多対多の共有参照リレーションシップのマッピング

@ManyToMany注釈は、ソース・エンティティの1つ以上のインスタンスが、ターゲット・エンティティの1つ以上のインスタンスを参照できることを示しています。DepartmentとEmployeeのリレーションシップは双方向なので、この例でも、EclipseLinkの@XmlInverseReference注釈を使用してバックポインタを表現しています。

多対多の共有参照リレーションシップをマップするには、次を実行します:

1. 15.2.1.1項「タスク1: アクセッサ・タイプの定義およびクラスのインポート」の説明に従って、アクセッサ・タイプFIELDがパッケージ・レベルで定義されていることを確認します。

2. 次のコードを挿入して、Departmentエンティティを作成します。

@Entity
public class Department {

3. 次のコードを挿入して、多対多のリレーションシップおよびエンティティの結合表を、このエンティティに定義します。

@ManyToMany
@JoinTable(name="DEPT_EMP", joinColumns =
@JoinColumn(name="D_ID", referencedColumnName = "D_ID"),
inverseJoinColumns = @JoinColumn(name="E_ID",
referencedColumnName = "E_ID"))

このコードにより、DEPT_EMPという結合表が作成され、外部キーが格納される列(name="E_ID")および外部キーによって参照される列(referencedColumnName = "E_ID")が指定されます。さらに、関連付けの逆側のプライマリ表も指定されます。

4. 最初のマッピング(この場合は、Departmentのemployeeプロパティ)を完了し、次のコードを挿入して、それをこのエンティティの外部キーにします。

@XmlIDREF
private List<Employee> member;

5. 15.2.1.2.1項「1対1および埋込みリレーションシップのマッピング」で作成したEmployeeエンティティに、次のコードを挿入して、eIdがJPA (@Id注釈)およびJAXB (@XmlID注釈)の主キーであることを指定します。

@Id
@Column(name="E_ID")
@XmlID
private BigDecimal eId;

6. さらにEmployeeエンティティに、次のコードを挿入して、リターン・マッピングを指定します。

@ManyToMany(mappedBy="member")
@XmlInverseReference(mappedBy="member")
private List<Department> team;

エンティティは、例15-1および例15-4に示すエンティティと同じように指定してください。

15.2.1.4 JPAエンティティ

マッピングが作成されると、エンティティは次の例のようになります。

- 例15-1「Employeeエンティティ」

- 例15-2「Addressエンティティ」

- 例15-3「PhoneNumberエンティティ」

- 例15-4「Departmentエンティティ」

注意:

スペースを節約するために、パッケージ名、import文、およびget/setメソッドは、コード・サンプルから除かれています。すべての例で、標準のJPA注釈が使用されています。

例15-1 Employeeエンティティ

@Entity
public class Employee {

@Id
@Column(name="E_ID")
private BigDecimal eId;

private String name;

@OneToOne(mappedBy="resident")
private Address residence;

@OneToMany(mappedBy="contact")
private List<PhoneNumber> contactNumber;

@ManyToMany(mappedBy="member")
private List<Department> team;

}

例15-2 Addressエンティティ

@Entity
public class Address {

@Id
@Column(name="E_ID", insertable=false, updatable=false)
private BigDecimal eId;

private String city;

private String street;

@OneToOne
@JoinColumn(name="E_ID")
private Employee resident;

}

例15-3 PhoneNumberエンティティ

@Entity
@Table(name="PHONE_NUMBER")
public class PhoneNumber {

@Id
@Column(name="P_ID")
private BigDecimal pId;

@ManyToOne
@JoinColumn(name="E_ID", referencedColumnName = "E_ID")
private Employee contact;

private String num;

}

例15-4 Departmentエンティティ

@Entity
public class Department {

@Id
@Column(name="D_ID")
private BigDecimal dId;

private String name;

@ManyToMany
@JoinTable(name="DEPT_EMP", joinColumns =
@JoinColumn(name="D_ID", referencedColumnName = "D_ID"),
inverseJoinColumns = @JoinColumn(name="E_ID",
referencedColumnName = "E_ID"))
private List<Employee> member;

}

15.2.2 XMLへの複合主キーのバインディング

JPAエンティティに複合主キーがある場合、次の例のように、JAXB注釈およびEclipseLinkの特定の拡張機能を使用してバインドできます。

15.2.2.1 タスク1: XMLアクセッサ・タイプの定義

15.2.1.1項「タスク1: アクセッサ・タイプの定義およびクラスのインポート」の説明に従って、アクセッサ・タイプにFIELDを定義します。

15.2.2.2 タスク2: ターゲット・オブジェクトの作成

ターゲット・オブジェクトを作成するには、次を実行します:

1. エンティティの複数のフィールドまたはプロパティにマップするためのEmployeeIDというコンポジット主キー・クラスを指定して、Employeeを作成します。

@Entity
@IdClass(EmployeeId.class)
public class Employee {

2. エンティティの最初の主キーeIdを指定して、列にマップします。

@Id
@Column(name="E_ID")
@XmlID
private BigDecimal eId;

3. 2番目の主キーcountryを指定します。この場合、@XmlIDの注釈を付けられるのは1つのプロパティ(eId)のみなので、@XmlKeyを使用して主キーを指定する必要があります。

@Id
@XmlKey
private String country;

@XmlKey注釈により、ソース・オブジェクトの@XmlJoinNode注釈を介したキーに基づくマッピングを使用して参照されるキーとして、プロパティがマーク付けされます。スキーマ・タイプIDにプロパティをバインドする必要がない点以外は@XmlKey注釈に似ています。これは、@XmlKey注釈の一般的な適用方法です。

4. 次のコードを挿入して、PhoneNumberのEmployeeプロパティの1対多マッピングを作成します。

@OneToMany(mappedBy="contact")
@XmlInverseReference(mappedBy="contact")
private List<PhoneNumber> contactNumber;

Employeeエンティティは例15-5のようになります。

例15-5 複合主キーが設定されたEmployeeエンティティ

@Entity
@IdClass(EmployeeId.class)
public class Employee {

@Id
@Column(name="E_ID")
@XmlID
private BigDecimal eId;

@Id
@XmlKey
private String country;

@OneToMany(mappedBy="contact")
@XmlInverseReference(mappedBy="contact")
private List<PhoneNumber> contactNumber;

}

public class EmployeeId {
public BigDecimal eId;
public String country;

public EmployeeId(BigDecimal eId, String country) {
this.id = id;
this.country = country;;
}

public boolean equals(Object other) {
if (other instanceof EmployeeId) {
final EmployeeId otherEmployeeId = (EmployeeId) other;
return (otherEmployeeId.eId.equals(eId) && otherEmployeeId.country.equals(country));
}

return false;
}
}

15.2.2.3 タスク3: ソース・オブジェクトの作成

このタスクでは、ソース・オブジェクトPhoneNumberエンティティを作成します。ターゲット・オブジェクトに複合キーがあるので、EclipseLinkの@XmlJoinNodes注釈を使用してマッピングを設定する必要があります。

ソース・オブジェクトを作成するには:

1. PhoneNumberエンティティを作成します。

@Entity
public class PhoneNumber {

2. 多対1のリレーションシップを作成して、結合列を定義します。

@ManyToOne
@JoinColumns({
@JoinColumn(name="E_ID", referencedColumnName = "E_ID"),
@JoinColumn(name="E_COUNTRY", referencedColumnName = "COUNTRY")
})

3. EclipseLinkの@XmlJoinNodes注釈を使用して、マッピングを設定します。

@XmlJoinNodes( {
@XmlJoinNode(xmlPath="contact/id/text()", referencedXmlPath="id/text()"),
@XmlJoinNode(xmlPath="contact/country/text()", referencedXmlPath="country/text()")
})

4. contactプロパティを定義します。

private Employee contact;

}

ターゲット・オブジェクトは例15-6のようになります。

例15-6 PhoneNumberエンティティ

@Entity
public class PhoneNumber {

@ManyToOne
@JoinColumns({
@JoinColumn(name="E_ID", referencedColumnName = "E_ID"),
@JoinColumn(name="E_COUNTRY", referencedColumnName = "COUNTRY")
})
@XmlJoinNodes( {
@XmlJoinNode(xmlPath="contact/id/text()", referencedXmlPath="id/text()"),
@XmlJoinNode(xmlPath="contact/country/text()", referencedXmlPath="country/text()")
})
private Employee contact;

}

15.2.3 XMLへの埋込みIDクラスのバインディング

埋込みIDでは、エンティティの主キーを格納する別個のEmbeddable Javaクラスを定義します。これは@EmbeddedId注釈を使用して定義します。埋込みIDのEmbeddableクラスには、基本マッピングを使用してエンティティの各ID属性を定義する必要があります。埋込みIDのEmbeddableのすべての属性は、主キーの一部であると見なされます。この演習では、JPAエンティティに埋込みIDクラスがある場合に、JAXBを使用して一連のJPAエンティティからXML表現を導出する方法を示します。

15.2.3.1 タスク1: XMLアクセッサ・タイプの定義

15.2.1.1項「タスク1: アクセッサ・タイプの定義およびクラスのインポート」の説明に従って、XMLアクセッサ・タイプにFIELDを定義します。

15.2.3.2 タスク2: ターゲット・オブジェクトの作成

ターゲット・オブジェクトはEmployeeというエンティティで、従業員の連絡先電話番号のマッピングが格納されています。このターゲット・オブジェクトを作成するには、DescriptorCustomizerインタフェースを実装する必要があるので、EclipseLinkの@XmlCustomizer注釈を含める必要があります。また、リレーションシップが双方向なので、@XmlInverseReference注釈も実装する必要があります。

ターゲット・オブジェクトを作成するには:

1. Employeeエンティティを作成します。@IdClass注釈を使用し、EmployeeIDクラスがエンティティの複数のプロパティにマップされるようにします。

@Entity
@IdClass(EmployeeId.class)
public class Employee {
}

2. idプロパティを定義して、埋込み可能にします。

@EmbeddedId
@XmlPath(".");
private EmployeeId id;

3. 1対多のマッピング(この場合は、PhoneNumberのemployeeプロパティ)を定義します。リレーションシップが双方向なので、@XmlInverseReferenceを使用してリターン・マッピングを定義します。mappedBy引数で示されているように、これら両方のリレーションシップはcontactフィールドによって所有されます。

@OneToMany(mappedBy="contact")
@XmlInverseReference(mappedBy="contact")
private List<PhoneNumber> contactNumber;

完成したターゲット・オブジェクトは例15-7のようになります。

例15-7 ターゲット・オブジェクトとしてのEmployeeエンティティ

@Entity
@IdClass(EmployeeId.class)
@XmlCustomizer(EmployeeCustomizer.class)
public class Employee {

@EmbeddedId
private EmployeeId id;

@OneToMany(mappedBy="contact")
@XmlInverseReference(mappedBy="contact")
private List<PhoneNumber> contactNumber;

}

15.2.3.3 タスク3: ソース・オブジェクトの作成

この例のソース・オブジェクトには複合キーがあるので、キーが自分自身にマップされるのを防ぐために、フィールド@XmlTransientをマーク付けする必要があります。EclipseLinkの@XmlCustomizer注釈を使用してマッピングを設定します。

ソース・オブジェクトを作成するには、次を実行します:

1. PhoneNumberエンティティを作成します。

@Entity
public class PhoneNumber {
}

2. 多対1のマッピングを作成して、結合列を定義します。

@ManyToOne
@JoinColumns({
@JoinColumn(name="E_ID", referencedColumnName = "E_ID"),
@JoinColumn(name="E_COUNTRY", referencedColumnName = "COUNTRY")
})

3. EclipseLinkの注釈拡張である@XmlJoinNodesを使用し、マッピングにXMLノードを定義します。ターゲット・オブジェクトのIDが1つである場合、@XmlIDREF注釈を使用します。

@XmlJoinNodes( {        @XmlJoinNode(xmlPath="contact/id/text()", referencedXmlPath="id/text()"),        @XmlJoinNode(xmlPath="contact/country/text()", referencedXmlPath="country/text()")    })
private Employee contact;

完成したPhoneNumberクラスは例15-8のようになります。

例15-8 ソース・オブジェクトとしてのPhoneNumberクラス

@Entity
public class PhoneNumber {

@ManyToOne
@JoinColumns({
@JoinColumn(name="E_ID", referencedColumnName = "E_ID"),
@JoinColumn(name="E_COUNTRY", referencedColumnName = "COUNTRY")
})
@XmlJoinNodes( {
@XmlJoinNode(xmlPath="contact/id/text()", referencedXmlPath="id/text()"),
@XmlJoinNode(xmlPath="contact/country/text()", referencedXmlPath="country/text()")
})
private Employee contact;

}

15.2.3.4 タスク5: PhoneNumberCustomizerクラスとしてのDescriptorCustomizerの実装

タスク4で追加したコードは、新しい値に対してXMLObjectReferenceMappingsを作成する必要があることを示していました。これには、DescriptorCustomizerをPhoneNumberCustomizerとして実装して、複数のキー・マッピングを追加する必要があります。これを行うには:

1. DescriptorCustomizerをPhoneNumberCustomizerとして実装します。org.eclipse.persistence.oxm.mappings.XMLObjectReferenceMappingを必ずインポートしてください。

import org.eclipse.persistence.oxm.mappings.XMLObjectReferenceMapping;

public class PhoneNumberCustomizer implements DescriptorCustomizer {

2. customizeメソッドで、次のマッピングを更新します。

- contactMapping.setAttributeNameを"contact"にします。

- contactMapping.addSourceToTargetKeyFieldAssociationを"contact/@eID", "eId/text()"にします。

- contactMapping.addSourceToTargetKeyFieldAssociationを"contact/@country", "country/text()"にします。

PhoneNumberCustomizerは例15-9のようになります。

例15-9 更新されたキー・マッピングが指定されたPhoneNumber Customizer

import org.eclipse.persistence.config.DescriptorCustomizer;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.oxm.mappings.XMLObjectReferenceMapping;

public class PhoneNumberCustomizer implements DescriptorCustomizer {

public void customize(ClassDescriptor descriptor) throws Exception {
XMLObjectReferenceMapping contactMapping = new XMLObjectReferenceMapping();
contactMapping.setAttributeName("contact");
contactMapping.setReferenceClass(Employee.class);
contactMapping.addSourceToTargetKeyFieldAssociation("contact/@eID", "eId/text()");
contactMapping.addSourceToTargetKeyFieldAssociation("contact/@country", "country/text()");
descriptor.addMapping(contactMapping);
}

}

15.2.4 EclipseLinkのXMLバインディング文書の使用

前述の例で示したように、EclipseLinkには、JPAエンティティをXML表現にマップする標準のJAXB注釈が実装されています。EclipseLinkのXMLバインディング文書を使用して、メタデータを表現することもできます。XMLバインディングを使用してマッピング情報を実際のJavaクラスから分離できるだけでなく、次のようなさらに高度なメタデータ・タスクに使用することもできます。

- 追加のマッピング情報による、既存の注釈の増強またはオーバーライド。

- Java注釈を使用しない、すべてのマッピング情報の外部指定。

- 複数のバインディング文書間のマッピングの定義。

- 具体的なJavaフィールドに対応しない「仮想」マッピングの指定。

XMLバインディング文書の使用の詳細は、http://wiki.eclipse.org/EclipseLink/UserGuide/MOXy/Runtime/XML_BindingsにあるJAXB/MOXyのドキュメントのXMLバインディングに関する項を参照してください。

15.3 XMLテキスト・ノードへの単純なJava値のマッピング

この項では、単純なJava値をXMLテキスト・ノードに直接マップする方法をいくつか示します。次の例を示します。

- 属性に対する値のマッピング

- テキスト・ノードに対する値のマッピング

15.3.1 属性に対する値のマッピング

この例では、JavaオブジェクトCustomerのidプロパティを、<customer>要素の属性として、そのXML表現にマップします。このXMLは例15-10のスキーマに基づいています。

例15-10 XMLスキーマの例

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsd:element name="customer" type="customer-type"/>

<xsd:complexType name="customer-type">
<xsd:attribute name="id" type="xsd:integer"/>
</xsd:complexType>

</xsd:schema>

次の手順では、Javaオブジェクトのidプロパティをマップする方法、つまり、EclipseLinkのObject-to-XML Mapping (OXM)メタデータ形式で値を表す方法を説明します。

15.3.1.1 Javaオブジェクトからのマッピング

Javaオブジェクトからこのマッピングを作成するために重要なのは、フィールドをXML属性にマップする@XmlAttribute JAXB注釈です。このマッピングを作成するには:

1. オブジェクトを作成して、javax.xml.bind.annotation.*をインポートします。

package example;

import javax.xml.bind.annotation.*;

2. Customerクラスを宣言し、@XmlRootElement注釈を使用してルート要素にします。XMLアクセッサ・タイプにFIELDを設定します。

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {

3. Customerクラスのidプロパティを属性としてマップします。

@XmlAttribute
private Integer id;

このオブジェクトは例15-11のようになります。

例15-11 マップされたidプロパティが設定されたCustomerオブジェクト

package example;

import javax.xml.bind.annotation.*;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {
@XmlAttribute
private Integer id;

...
}

15.3.1.2 OXMメタデータ形式でのマッピングの定義

EclipseLinkのOXMメタデータ形式でマッピングを表す必要がある場合は、例15-12のとおり、eclipselink-oxm.xmlファイルに定義されているXMLタグを使用して、適切な値を設定する必要があります。

例15-12 OXMメタデータ形式の属性としてのidのマッピング

...
<java-type name="Customer">
<xml-root-element name="customer"/>
<java-attributes>
<xml-attribute java-attribute="id"/>
</java-attributes>
</java-type>
...

OXMメタデータ形式の詳細は、15.4項「XMLメタデータ表現を使用したJAXB注釈のオーバーライド」を参照してください。

15.3.2 テキスト・ノードへの値のマッピング

EclipseLinkでは、たとえば、単純なテキスト・ノード、単純な順序のテキスト・ノード、サブセットまたは位置別など、様々な種類のXMLテキスト・ノードにJavaオブジェクトから値を簡単にマップできます。これらのマッピングを次の例に示します。

- 単純なテキスト・ノードに対する値のマッピング

- 単純な順序でのテキスト・ノードへの値のマッピング

- サブ要素のテキスト・ノードに対する値のマッピング

- 位置によるテキスト・ノードへの値のマッピング

15.3.2.1 単純なテキスト・ノードに対する値のマッピング

JavaオブジェクトのJAXB注釈を使用して、またはEclipseLinkのOXMメタデータ形式でマッピングを表して、Javaオブジェクトから値をマップできます。

15.3.2.1.1 JAXB注釈を使用したマッピング

文字列値を受け入れる<phone-number>という要素が、関連するスキーマに定義されている場合は、@XmlValue注釈を使用して、<phone-number>ノードに文字列をマップできます。次を実行します:

1. オブジェクトを作成して、javax.xml.bind.annotation.*をインポートします。

package example;

import javax.xml.bind.annotation.*;

2. PhoneNumberクラスを宣言し、@XmlRootElement注釈を使用して、そのクラスをphone-numberという名前のルート要素にします。XMLアクセッサ・タイプにFIELDを設定します。

@XmlRootElement(name="phone-number")
@XmlAccessorType(XmlAccessType.FIELD)
public class PhoneNumber {

3. Customerクラスのnumberプロパティの前の行に@XmlValue注釈を挿入し、この値を属性としてマップします。

@XmlValue
private String number;

このオブジェクトは例15-13のようになります。

例15-13 マップされたnumberプロパティが指定されたPhoneNumberオブジェクト

package example;

import javax.xml.bind.annotation.*;

@XmlRootElement(name="phone-number")
@XmlAccessorType(XmlAccessType.FIELD)
public class PhoneNumber {
@XmlValue
private String number;

...
}

15.3.2.1.2 OXMメタデータ形式でのマッピングの定義

EclipseLinkのOXMメタデータ形式でマッピングを表す必要がある場合は、例15-14のとおり、eclipselink-oxm.xmlファイルに定義されているXMLタグを使用して、適切な値を設定する必要があります。

例15-14 OXMメタデータ形式の属性としてのnumberのマッピング

...
<java-type name="PhoneNumber">
<xml-root-element name="phone-number"/>
<java-attributes>
<xml-value java-attribute="number"/>
</java-attributes>
</java-type>
...

15.3.2.2 単純な順序でのテキスト・ノードへの値のマッピング

JAXB注釈を使用して、またはEclipseLinkのOXMメタデータ形式でマッピングを表して、顧客の名と姓のような値の順序を個別の要素としてマップできます。次の手順では、顧客の名と姓の値をマップする方法を示しています。

15.3.2.2.1 JAXB注釈を使用したマッピング

関連するスキーマに次の要素が定義されていると仮定します。

- それ自身がcomplexTypeとして定義されている、タイプcustomer-typeの<customer>。

- 両方ともタイプstringの<first-name>および<last-name>という名前の順序要素。

@XmlElement注釈を使用すれば、顧客の名と姓の値を適切なXMLノードにマップできます。これを行うには:

1. オブジェクトを作成して、javax.xml.bind.annotation.*をインポートします。

package example;

import javax.xml.bind.annotation.*;

2. Customerクラスを宣言し、@XmlRootElement注釈を使用してルート要素にします。XMLアクセッサ・タイプにFIELDを設定します。

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {

3. firstnameおよびlastnameプロパティを定義して、@XmlElement注釈で注釈を付けます。name=引数を使用して、XML要素名をカスタマイズします(name=で名前を明示的に設定していないと、XML要素では、Java属性名が照合されます。たとえば、ここでは、<first-name>要素の組合せが、<firstName> </firstName>とXMLに指定されます)。

@XmlElement(name="first-name")
private String firstName;

@XmlElement(name="last-name")
private String lastName;

このオブジェクトは例15-15のようになります。

例15-15 単純な順序に対するCustomerオブジェクトの値のマッピング

package example;

import javax.xml.bind.annotation.*;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {
@XmlElement(name="first-name")
private String firstName;

@XmlElement(name="last-name")
private String lastName;

...
}

15.3.2.2.2 OXMメタデータ形式でのマッピングの定義

EclipseLinkのOXMメタデータ形式でマッピングを表す必要がある場合は、例15-16のとおり、eclipselink-oxm.xmlファイルに定義されているXMLタグを使用して、適切な値を設定する必要があります。

例15-16 OXMメタデータ形式での順序属性のマッピング

...
<java-type name="Customer">
<xml-root-element name="customer"/>
<java-attributes>
<xml-element java-attribute="firstName" name="first-name"/>
<xml-element java-attribute="lastName" name="last-name"/>
</java-attributes>
</java-type>
...

15.3.2.3 サブ要素のテキスト・ノードに対する値のマッピング

JAXB注釈を使用して、またはEclipseLinkのOXMメタデータ形式でマッピングを表して、XML文書のサブ要素としてネストされているテキスト・ノードに、Javaオブジェクトから値をマップできます。たとえば、<customer>ルートの<personal-info>のサブ要素である<first-name>および<last-name>要素に値を設定する必要がある場合は、次の手順でマッピングを設定できます。

15.3.2.3.1 JAXB注釈を使用したマッピング

関連するスキーマに次の要素が定義されていると仮定します。

- それ自身がcomplexTypeとして定義されている、タイプcustomer-typeの<customer>

- <personal-info>

- 両方ともタイプstringの<first-name>と<last-name>という名前の<personal-info>のサブ要素

JAXBの注釈を使用すれば、顧客の名と姓の値を適切なXMLサブ要素ノードにマップできます。この例では、単純な要素名のカスタマイズではなく、実際に新しいXML構造が導入されているので、EclipseLinkの@XmlPath注釈を使用しています。このマッピングを実現するには:

1. オブジェクトを作成して、javax.xml.bind.annotation.*およびorg.eclipse.persistence.oxm.annotations.*をインポートします。

package example;

import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.*;

2. Customerクラスを宣言し、@XmlRootElement注釈を使用してルート要素にします。XMLアクセッサ・タイプにFIELDを設定します。

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {

3. firstNameおよびlastNameプロパティを定義します。

4. プロパティ宣言の直前の行に@XmlPath注釈を挿入して、XMLスキーマによって定義されたサブ要素にfirstNameおよびlastNameプロパティをマップします。各注釈に対して、適切なXPath述語を指定してマッピングを定義します。

@XmlPath("personal-info/first-name/text()")
private String firstName;

@XmlPath("personal-info/last-name/text()")
private String lastName;

このオブジェクトは例15-17のようになります。

例15-17 プロパティをサブ要素にマッピングするCustomerオブジェクト

package example;

import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.*;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {
@XmlPath("personal-info/first-name/text()")
private String firstName;

@XmlPath("personal-info/last-name/text()")
private String lastName;

...
}

15.3.2.3.2 OXMメタデータ形式でのマッピングの定義

EclipseLinkのOXMメタデータ形式でマッピングを表す必要がある場合は例15-18のとおり、、eclipselink-oxm.xmlファイルに定義されているXMLタグを使用して、適切な値を設定する必要があります。

例15-18 OXMメタデータ形式のサブ要素としての属性のマッピング

...
<java-type name="Customer">
<xml-root-element name="customer"/>
<java-attributes>
<xml-element java-attribute="firstName" xml-path="personal-info/first-name/text()"/>
<xml-element java-attribute="lastName" xml-path="personal-info/last-name/text()"/>
</java-attributes>
</java-type>
...

15.3.2.4 位置によるテキスト・ノードへの値のマッピング

複数のノードの名前が同じ場合には、XML文書内の位置を指定して、Javaオブジェクトから値をマップします。これを行うには、属性の名前ではなく、属性の位置に値をマップします。これは、JAXB注釈を使用するか、EclipseLinkのOXMメタデータ形式でマッピングを表すことによって行えます。次の例では、2つの<name>要素がXMLに含まれています。最初の名前は顧客の名を表し、2番名の名前は顧客の姓を表しています。

15.3.2.4.1 JAXB注釈を使用したマッピング

次の属性が定義されたXMLスキーマがあるとします。

- それ自身がcomplexTypeとして定義されている、タイプcustomer-typeの<customer>

- タイプStringの<name>

この例でも、JAXBの@XmlPath注釈を使用して、顧客の名と姓を適切な<name>要素にマップします。また、@XmlType(propOrder)注釈も使用して、要素が常に正しい位置に配置されるようにします。このマッピングを実現するには:

1. オブジェクトを作成して、javax.xml.bind.annotation.*およびorg.eclipse.persistence.oxm.annotations.XmlPathをインポートします。

package example;

import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;

2. Customerクラスを宣言して、"firstName"引数の後に"lastName"引数が指定された@XmlType(propOrder)注釈を挿入します。@XmlRootElement注釈を挿入して、Customerをルート要素にし、XMLアクセッサ・タイプにFIELDを指定します。

@XmlRootElement
@XmlType(propOrder={"firstName", "lastName"})
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {

3. タイプStringが指定されたプロパティfirstNameおよびlastNameを定義します。

4. 適切なXPath述語が指定された@XmlPathを挿入して、プロパティfirstNameおよびlastNameをXML文書の適切な位置にマップします。

@XmlPath("name[1]/text()")
private String firstName;

@XmlPath("name[2]/text()")
private String lastName;

述語"name[1]/text()"および"name[2]/text()"は、特定のプロパティがマップされる<name>要素を示しています。たとえば、"name[1]/text"はfirstNameプロパティを最初の<name>要素にマップします。

このオブジェクトは例15-19のようになります。

例15-19 位置により値をマップするCustomerオブジェクト

package example;

import javax.xml.bind.annotation.*;

import org.eclipse.persistence.oxm.annotations.XmlPath;

@XmlRootElement
@XmlType(propOrder={"firstName", "lastName"})
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {
@XmlPath("name[1]/text()")
private String firstName;

@XmlPath("name[2]/text()")
private String lastName;

...
}

XPath述語の使用方法の詳細は、15.5項「マッピング用のXPath述語の使用」を参照してください。

15.4 XMLメタデータ表現を使用したJAXB注釈のオーバーライド

EclipseLinkには、Java注釈の使用に加えて、JAXB注釈のかわりに使用したり、ソースのJAXB注釈をメタデータのXML表現で置換したりできるeclipselink-oxm.xmlという名前のXMLマッピング構成ファイルが用意されています。すべての標準JAXBマッピング機能を使用できるだけでなく、高度なマッピング・タイプとオプションも使用できます。

XMLのメタデータ表現は、次の場合に便利です。

- サード・パーティから入手したなどの理由でドメイン・モデルを変更できない場合。

- JAXBのAPIにコンパイル時の依存関係が存在しないようにする必要がある場合(Java SE 6より前のバージョンのJavaを使用している場合)。

- 複数のJAXBマッピングをドメイン・モデルに適用する必要がある場合(注釈では1つに制限されます)。

- 他のテクノロジからの多数の注釈がすでにオブジェクト・モデルに含まれているので、さらに追加するとクラスが読みにくくなる場合。

この項では、eclipselink-oxm.xmlを使用してJAXBの注釈をオーバーライドする方法を示します。

注意:

このマッピング・ファイルを使用すると多くの高度な機能が有効になりますが、他のJAXBの実装に移植できなくなる場合があります。

15.4.1 タスク1: XMLでの高度なマッピングの定義

まず、XMLマッピング・ファイルを更新して、eclipselink_oxm_2_3.xsdスキーマを公開します。例15-20は、マッピング・ファイルの<xml-bindings>要素を変更し、正しいネームスペースを指して、スキーマを利用する方法を示しています。各Javaパッケージには1つのマッピング・ファイルを指定できます。

例15-20 マッピング・ファイル内のXMLバインディング情報の更新

<?xml version="1.0"?>
<xml-bindings
xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.eclipse.org/eclipselink/xsds/persistence/oxm  http://www.eclipse.org/eclipselink/xsds/eclipselink_oxm_2_4.xsd"
version="2.4">
</xml-bindings>

15.4.2 タスク2: JAXBContextの使用方法の構成

次に、オブジェクトのJAXBContextにマッピング・ファイルを渡します。

1. 次のコードを挿入して、外部化されたメタデータを指定します。

Map<String, Object> properties = new HashMap<String, Object>(1);
properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, "org/example/oxm.xml);
JAXBContext.newInstance("org.example', aClassLoader, properties);

2. JAXBContextに渡すプロパティ・オブジェクトを作成します。この例では、次のようになります。

Map<String,Object> properties = new HashMap<String,Object>();
properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, metadata);

3. JAXBContextを作成します。この例では、次のようになります。

JAXBContext.newInstance("example.order:example.customer", aClassLoader, properties);

15.4.3 タスク3: JAXB実装としてのMOXyの指定

MOXyをJAXB実装として使用する必要があります。これを行うには、次を実行します:

1. jaxb.propertiesファイルをオープンして、次の行を追加します。

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

2. ドメイン・クラスが格納されたパッケージにjaxb.propertiesファイルをコピーします。

15.5 マッピングに対するXPath述語の使用

この項では、EclipseLinkのMOXy APIでXPath述語を使用して、XML要素の名前を指定する式を定義する方法を説明します。XPath述語とは、オブジェクトからXMLへの特定のマッピングを定義する式のことです。前述の例で示したように、JAXBのデフォルトでは、Javaのフィールド名がXML要素名として使用されます。

この項には次のサブセクションがあります。

- 15.5.1項「XPath述語の理解」

- 15.5.2項「位置に基づくマッピング」

- 15.5.3項「属性値に基づくマッピング」

- 15.5.4項「セルフ・マッピング」

15.5.1 XPath述語の理解

前述のとおり、XPath述語とは、標準の注釈時にオブジェクトからXMLへの特定のマッピングを定義する式のことです。

十分ではありません。たとえば、XMLの次のスニペットは、2つの<node>サブ要素が指定された<data>要素を示しています。このマッピングをJavaオブジェクトに作成する場合は、各<node>サブ要素にXPath述語を指定する必要があります。たとえば、次のJavaでは、Node[2]と指定されています。

<java-attributes>
<xml-element java-attribute="node" xml-path="node[1]/ABC"/>
<xml-element java-attribute="node" xml-path="node[2]/DEF"/>
</java-attributes>

これは、次のXMLで2番目に出現するnode要素("DEF")と一致します。

<?xml version="1.0" encoding="UTF-8"?>
<data>
<node>ABC</node>
<node>DEF</node>
</data>

このように、XPath述語を使用すれば、異なる属性値に対して同じ属性名を使用できます。

15.5.2 位置に基づくマッピング

このマッピング方法は、15.3.2.4項「位置によるテキスト・ノードへの値のマッピング」に説明されています。

15.5.3 属性値に基づくマッピング

EclipseLink MOXy 2.3以降では、属性値に基づいてXML要素にマップすることもできます。この演習では、JPAエンティティに注釈を付けて、例15-21に示されているXML文書をレンダリングします。すべてのXML要素は名前付きノードですが、名前属性の値によって区別されていることに注意してください。

例15-21

<?xml version="1.0" encoding="UTF-8"?>
<node>
<node name="first-name">Bob</node>
<node name="last-name">Smith</node>
<node name="address">
<node name="street">123 A Street</node>
</node>
<node name="phone-number" type="work">555-1111</node>
<node name="phone-number" type="cell">555-2222</node>
</node>

このマッピングを実現するには、Name、AddressおよびPhoneNumberの3つのクラスを宣言し、element-name[@attribute-name='value']の形式でXPathを使用して、各Javaフィールドをマップする必要があります。

15.5.3.1 タスク1: Customerエンティティの作成

Customerクラス・エンティティを作成するには:

1. 次のコードを追加して、必要なJPAパッケージをインポートします。

import javax.xml.bind.annotation.*;

import org.eclipse.persistence.oxm.annotations.XmlPath;

2. Customerクラスを宣言し、@XmlRootElement注釈を使用してルート要素にします。XMLアクセッサ・タイプにFIELDを設定します。

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {

3. Customerクラスに対して、次のプロパティをローカルに宣言します。

- firstName (文字列型)

- lastName (文字列)

- Address (住所)

@XmlPath(element-name[@attribute-name='value'])をプロパティ宣言の前に記述することにより、各プロパティに対してXPath述語を設定します。たとえば、firstNameの場合は、次の文でXPath述語を設定します。

@XmlPath("node[@name='first-name']/text()")

4. また、Customerクラスに対してphoneNumberプロパティをList<PhoneNumber>タイプでローカルに宣言し、値new ArrayList<PhoneNumber>()をそれに割り当てます。

Customerクラスは例15-22のスニペットのようになります。

例15-22 属性値にマッピングされているCustomerオブジェクト

package example;

import javax.xml.bind.annotation.*;

import org.eclipse.persistence.oxm.annotations.XmlPath;

@XmlRootElement(name="node")
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {

@XmlPath("node[@name='first-name']/text()")
private String firstName;

@XmlPath("node[@name='last-name']/text()")
private String lastName;

@XmlPath("node[@name='address']")
private Address address;

@XmlPath("node[@name='phone-number']")
private List<PhoneNumber> phoneNumbers = new ArrayList<PhoneNumber>();

...
}

15.5.3.2 タスク2: Addressエンティティの作成

Addressクラスを作成するには、次を実行します:

1. 次のコードを追加して、必要なJPAパッケージをインポートします。

import javax.xml.bind.annotation.*;

import org.eclipse.persistence.oxm.annotations.XmlPath;

2. Addressクラスを宣言して、XMLアクセッサ・タイプにFIELDを設定します。

@XmlAccessorType(XmlAccessType.FIELD)
public class Address {

AddressクラスがXML文書のルート要素ではないので、このインスタンスには、前述のタスクのように@XmlRootElement注釈は必要ありません。

3. StringプロパティstreetをAddressクラスに対してローカルに宣言します。注釈@XmlPath("node[@name='street']/text()")をプロパティ宣言の前に記述して、XPath述語を設定します。

Addressクラスは例15-23のようになります。

例15-23 属性値に対するAddressオブジェクトのマッピング

package example;

import javax.xml.bind.annotation.*;

import org.eclipse.persistence.oxm.annotations.XmlPath;

@XmlAccessorType(XmlAccessType.FIELD)
public class Address {

@XmlPath("node[@name='street']/text()")
private String street;

...
}

15.5.3.3 タスク3: PhoneNumberエンティティの作成

PhoneNumberエンティティを作成するには:

1. 次のコードを追加して、必要なJPAパッケージをインポートします。

import javax.xml.bind.annotation.*;

import org.eclipse.persistence.oxm.annotations.XmlPath;

2. PhoneNumberクラスを宣言し、@XmlRootElement注釈を使用して、クラスをルート要素にします。XMLアクセッサ・タイプにFIELDを設定します。

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {

3. typeおよびstringプロパティを作成し、@XmlAttribute注釈を使用して、PhoneNumberルート要素の属性としてマッピングを定義します。

@XmlAttribute
private String type;

@XmlValue
private String number;

PhoneNumberオブジェクトは例15-24のようになります。

例15-24 属性値に対するPhoneNumberオブジェクトのマッピング

package example;

import javax.xml.bind.annotation.*;

@XmlAccessorType(XmlAccessType.FIELD)
public class PhoneNumber {

@XmlAttribute
private String type;

@XmlValue
private String number;

...
}

15.5.4 セルフ・マッピング

セルフ・マッピングは、ターゲット・オブジェクトからのデータがソース・オブジェクトのXML要素内に表示されるようにターゲット・オブジェクトのXPathを"."(ドット)に設定した場合に、1対1のマッピングで発生します。この演習では、15.5.3項「属性値に基づくマッピング」の例を使用して、Addressの情報が、自分の要素にラップされずにcustomer要素に直接表示されるようにマップします。

セルフ・マッピングを作成するには:

1. 15.5.3.1項「タスク1: Customerエンティティの作成」のタスク1と2を繰り返します。

2. Customerクラスに対して、次のプロパティをローカルに宣言します。

- firstName (文字列型)

- lastName (文字列)

- Address (住所)

3. @XmlPath(element-name[@attribute-name='value'])をプロパティ宣言の前に記述することにより、firstNameおよびlastNameプロパティに対してXmlPath注釈を設定します。たとえば、firstNameの場合は、次の文でXPath述語を設定します。

@XmlPath("node[@name='first-name']/text()")

4. addressプロパティの@XmlPathに"."(ドット)を設定します。

@XmlPath(".")
private Address address;

5. また、Customerクラスに対してphoneNumberプロパティをList<PhoneNumber>タイプでローカルに宣言し、値new ArrayList<PhoneNumber>()をそれに割り当てます。

Customerエンティティに対してレンダリングされるXMLは例15-25のようになります。

例15-25 セルフ・マッピングされたAddress要素が指定されたXMLノード

<?xml version="1.0" encoding="UTF-8"?>
<node>
<node name="first-name">Bob</node>
<node name="last-name">Smith</node>
<node name="street">123 A Street</node>
<node name="phone-number" type="work">555-1111</node>
<node name="phone-number" type="cell">555-2222</node>
</node>

15.6 動的JAXB/MOXyの使用

動的JAXB/MOXyでは、様々なメタデータ・ソースからJAXBContextをブートストラップでき、コンパイルされたドメイン・クラスがなくても、使い慣れたJAXBのAPIを使用してデータのマーシャルおよびアンマーシャルを行えます。以前に生成されたJavaソース・コードを更新および再コンパイルしなくてもメタデータを更新できるようになったので、これは静的JAXBに対する拡張機能になります。

動的JAXB/MOXyのエンティティを使用すると、次のような利点があります。

- 実際のJavaクラス(たとえば、Customer.class、Address.class)を使用するかわりに、ドメイン・オブジェクトがDynamicEntityのサブクラスになります。

- 動的エンティティには、データを操作するためのget(propertyName)/set(propertyName propertyValue)という簡単なAPIが用意されています。

- 動的エンティティには、メタデータの解析時にメモリー内に生成されるDynamicTypeが関連付けられています。

次のタスクで、動的JAXBの使用方法を示します。

- タスク1: XMLスキーマからの動的JAXBContextのブートストラップ

- タスク2: 動的エンティティの作成とXMLへのマーシャル

- タスク3: XMLからの動的エンティティのアンマーシャル

15.6.1 タスク1: XMLスキーマからの動的JAXBContextのブートストラップ

この例は、XMLスキーマから動的JAXBContextをブートストラップする方法を示しています。

15.6.1.1 XMLスキーマからのブートストラップ

DynamicJAXBContextFactoryを使用して、動的JAXBContextを作成します。例15-26は、createContextFromXSD()を使用してDynamicJAXBContextをcustomer.xsdスキーマ(例15-27)からブートストラップしています。

例15-26 入力ストリームの指定およびDynamicJAXBContextの作成

import java.io.FileInputStream;

import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContextFactory;

public class Demo {

public static void main(String[] args) throws Exception {
FileInputStream xsdInputStream = new FileInputStream("src/example/customer.xsd");
DynamicJAXBContext jaxbContext =
DynamicJAXBContextFactory.createContextFromXSD(xsdInputStream, null, null, null);

最初のパラメータはXMLスキーマ自身を表し、java.io.InputStream、org.w3c.dom.Node、javax.xml.transform.Sourceのいずれかの形式である必要があります。

15.6.1.2 XMLスキーマ

例15-27は、ブートストラップする対象の動的JAXBContextのメタデータを表すcustomer.xsdスキーマを示しています。

例15-27 サンプルXMLスキーマ文書

<xsd:schema
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.example.org"
targetNamespace="http://www.example.org"
elementFormDefault="qualified">

<xsd:complexType name="address">
<xsd:sequence>
<xsd:element name="street" type="xsd:string" minOccurs="0"/>
<xsd:element name="city" type="xsd:string" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>

<xsd:element name="customer">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="name" type="xsd:string" minOccurs="0"/>
<xsd:element name="address" type="address" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>

</xsd:schema>

15.6.1.3 スキーマのインポート/インクルードの処理

他のスキーマのインポートが格納されたXMLスキーマからDynamicJAXBContextをブートストラップするには、org.xml.sax.EntityResolverを構成し、インポートされたスキーマの場所を解決して、EntityResolverをDynamicJAXBContextFactoryに渡す必要があります。

次の例は、customer.xsd (例15-28)とaddress.xsd (例15-29)の2つのスキーマ文書を示しています。次の文を使用して、customer.xsdがaddress.xsdをインポートしていることがわかります。

<xsd:import namespace="http://www.example.org/address" schemaLocation="address.xsd"/>

例15-28 customer.xsd

<?xml version="1.0" encoding="UTF-8"?>
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:add="http://www.example.org/address"
xmlns="http://www.example.org/customer"
targetNamespace="http://www.example.org/customer"
elementFormDefault="qualified">

<xsd:import namespace="http://www.example.org/address" schemaLocation="address.xsd"/>

<xsd:element name="customer">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="name" type="xsd:string" minOccurs="0"/>
<xsd:element name="address" type="add:address" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>

</xsd:schema>

例15-29 address.xsd

<?xml version="1.0" encoding="UTF-8"?>
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.example.org/address"
targetNamespace="http://www.example.org/address"
elementFormDefault="qualified">

<xsd:complexType name="address">
<xs:sequence>
<xs:element name="street" type="xs:string"/>
<xs:element name="city" type="xs:string"/>
</xs:sequence>
</xsd:complexType>

</xsd:schema>

15.6.1.4 EntityResolverを実装して渡す方法

DynamicJAXBContextをcustomer.xsdスキーマからブートストラップする場合は、エンティティ・リゾルバを渡す必要があります。次を実行します:

1. インポートされたスキーマの場所を解決するには、例15-30に示されたコードを指定して、entityResolverを実装する必要があります。

例15-30 EntityResolverの実装

class MyEntityResolver implements EntityResolver {

public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
// Imported schemas are located in ext\appdata\xsd\

// Grab only the filename part from the full path
String filename = new File(systemId).getName();

// Now prepend the correct path
String correctedId = "ext/appdata/xsd/" + filename;

InputSource is = new InputSource(ClassLoader.getSystemResourceAsStream(correctedId));
is.setSystemId(correctedId);

return is;
}

}

2. DynamicJAXBContextを実装した後、例15-31に示すようにEntityResolverを渡します。

例15-31 EntityResolverを渡す方法

FileInputStream xsdInputStream = new FileInputStream("src/example/customer.xsd");
DynamicJAXBContext jaxbContext =
DynamicJAXBContextFactory.createContextFromXSD(xsdInputStream, new MyEntityResolver(), null, null);

15.6.1.5 エラー処理

別のスキーマをインポートする際に、次の例外が表示される場合があります。

Internal Exception: org.xml.sax.SAXParseException: schema_reference.4: Failed to read schemadocument '<imported-schema-name>', because 1) could not find the document; 2) the document couldnot be read; 3) the root element of the document is not <xsd:schema>.

この例外を回避するには、noCorrectnessCheck Javaプロパティを設定して、XJCのスキーマ正当性チェックを無効にします。このプロパティは、次の2つのいずれかの方法で設定できます。

- コード内に次の行を追加します。

System.setProperty("com.sun.tools.xjc.api.impl.s2j.SchemaCompilerImpl.noCorrectnessCheck", "true")

- コマンドラインから次のコマンドを使用します。

-Dcom.sun.tools.xjc.api.impl.s2j.SchemaCompilerImpl.noCorrectnessCheck=true

15.6.1.6 ClassLoaderの指定

アプリケーションの現在のクラス・ローダーをclassLoaderパラメータとして使用します。このパラメータでは、新しいDynamicTypesが生成される前に、指定したクラスが存在することが確認されます。ほとんどの場合、このパラメータにnullを渡して、かわりにThread.currentThread().getContextClassLoader()を使用できます。

15.6.2 タスク2: 動的エンティティの作成とXMLへのマーシャル

この例は、動的エンティティを作成してXMLにマーシャルする方法を示しています。

15.6.2.1 動的エンティティの作成

DynamicJAXBContextを使用して、DynamicEntityのインスタンスを作成します。エンティティとプロパティ名は、静的JAXBを使用していれば生成されたであろうクラスとプロパティ名(この場合は、customerとaddress)に対応しています。

例15-32 動的エンティティの作成

DynamicEntity customer = jaxbContext.newDynamicEntity("org.example.Customer");
customer.set("name", "Jane Doe");

DynamicEntity address = jaxbContext.newDynamicEntity("org.example.Address");
address.set("street", "1 Any Street").set("city", "Any Town");
customer.set("address", address);

15.6.2.2 XMLへの動的エンティティのマーシャリング

DynamicJAXBContextから入手したマーシャラは、標準のマーシャラで、DynamicEntityのインスタンスをマーシャルするために通常どおり使用できます。

例15-33 標準の動的JAXBマーシャラ

Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);marshaller.marshal(customer, System.out);

例15-34に結果のXML文書を示します。

例15-34 <address>要素とその属性が表示された更新済のXML文書

<?xml version="1.0" encoding="UTF-8"?>
<customer xmlns="www.example.org">
<name>Jane Doe</name>
<address>
<street>1 Any Street</street>
<city>Any Town</city>
</address>
</customer>

15.6.3 タスク3: XMLからの動的エンティティのアンマーシャル

この例では、「タスク2: 動的エンティティの作成とXMLへのマーシャル」で作成した動的エンティティをXMLからアンマーシャルする方法を示します。参照されているXMLは例15-34に示されています。

15.6.3.1 XMLからの動的エンティティのアンマーシャル

DynamicJAXBContextから入手したアンマーシャラは、標準のアンマーシャラで、DynamicEntityのインスタンスをアンマーシャルするために通常どおり使用できます。

例15-35 標準の動的JAXBアンマーシャラ

FileInputStream xmlInputStream = new FileInputStream("src/example/dynamic/customer.xml");
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
DynamicEntity customer = (DynamicEntity) unmarshaller.unmarshal(xmlInputStream);

15.6.3.2 動的エンティティからのデータの取得

次に、動的エンティティのどのデータを取得するかを指定します。System.out.println()を使用して、この値を指定し、エンティティ名で渡します。DynamicEntityには、たとえば、getName()のかわりにget("name")のようなプロパティに基づいたデータ・アクセスが用意されています。

System.out.println(customer.<String>get("name"));

15.6.3.3 DynamicTypeを使用した、動的エンティティのイントロスペクション

DynamicEntityのインスタンスには、例15-36に示されているようにDynamicEntityをイントロスペクトするために使用できる、対応するDynamicTypeがあります。

例15-36

DynamicType addressType = jaxbContext.getDynamicType("org.example.Address");

DynamicEntity address = customer.<DynamicEntity>get("address");
for(String propertyName: addressType.getPropertiesNames()) {
System.out.println(address.get(propertyName));
}

15.7 その他の参考資料

この章のソリューションが実装されているその他のテクノロジおよびツールの詳細は、次の参考資料を参照してください。

- Oracle TopLinkによるJAXBアプリケーションの開発

16 JSONドキュメントからのオブジェクトの変換

この章では、JSON (JavaScript Object Notation)からまたはJSONへオブジェクトを変換する場合、Oracle TopLinkがそれをどのようにサポートするかを説明します。この機能は、RESTfulサービスを作成する際に便利です(JAX-RSサービスはXMLとJSONの両方のメッセージを受け取ります)。

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

- 16.1項「ソリューションの概要」

- 16.2項「ソリューションの実装」

- 16.3項「その他の参考資料」

ユース・ケース

JSONドキュメントからまたはJSONドキュメントへユーザーがオブジェクトを変換する必要があります。

解決方法

TopLinkでは、EclipseLinkのMOXyの実装を介してJSONをサポートしています。

コンポーネント

- TopLink 12cリリース1 (12.1.2)以上。

注意:

TopLinkのコア機能は、オープン・ソースのEclipse Foundationの永続性フレームワークであるEclipseLinkによって提供されています。EclipseLinkでは、Java Persistence API (JPA)、Java Architecture for XML Binding (JAXB)、および標準に基づいたその他の永続性テクノロジと、それらの標準の拡張が実装されます。TopLinkには、EclipseLinkのすべてに加え、Oracleの追加機能が含まれています。

- JSONドキュメント。

例

関連情報については、次のEclipseLinkの例を参照してください。

- http://wiki.eclipse.org/EclipseLink/Examples/MOXy

- http://wiki.eclipse.org/EclipseLink/Examples/MOXy/JSON_Metadata

- http://wiki.eclipse.org/EclipseLink/Examples/MOXy/MOXy_JSON_Provider

16.1 ソリューションの概要

EclipseLinkでは、JSONから読み書きをする際のMOXyのオブジェクトからXMLへのオプションをすべてサポートしています。

- (JAXB仕様に加え) EclipseLinkの高度な拡張マッピング機能

- 外部のバインディング・ファイルへのマッピングの保存

- 動的JAXBを使用した動的モデルの作成

- マルチテナント・アプリケーションをサポートする拡張可能なモデルの構築

16.2 ソリューションの実装

この項では、JSONドキュメントから、またJSONドキュメントにオブジェクトを変換する際の次のタスクについて説明します。

- タスク1: JSONドキュメントのマーシャリングおよびアンマーシャリング

- タスク2: JSONバインディングの指定

- タスク3: JSONデータ型の指定

- タスク4: 属性のサポート

- タスク5: ルート要素の非サポート

- タスク6: コレクションの使用

- タスク7: ルートレベル・コレクションのマッピング

- タスク8: テキスト値のラッピング

16.2.1 タスク1: JSONドキュメントのマーシャリングおよびアンマーシャリング

JAXBマーシャラまたはアンマーシャラのeclipselink.media-typeプロパティを使用すると、例16-1のとおり、アプリケーションでJSONドキュメントを作成および使用できます。

例16-1 マーシャリングおよびアンマーシャリング

...

Marshaller m = jaxbContext.createMarshaller();
m.setProperty("eclipselink.media-type", "application/json");

Unmarshaller u = jaxbContext.createUnmarshaller();
u.setProperty("eclipselink.media-type", "application/json");

...

また、例16-2のとおり、JAXBContextの作成時、使用しているプロパティのMapにeclipselink.media-typeプロパティを指定することもできます。

例16-2 Mapの使用

import org.eclipse.persistence.jaxb.JAXBContextProperties;
import org.eclipse.persistence.oxm.MediaType;

Map<String, Object> properties = new HashMap<String, Object>();
properties.put("eclipselink.media-type", "application/json");

JAXBContext ctx = JAXBContext.newInstance(new Class[] { Employee.class }, properties);
Marshaller jsonMarshaller = ctx.createMarshaller();
Unmarshaller jsonUnmarshaller = ctx.createUnmarshaller();

Mapに指定すると、JAXBContentから作成されたマーシャラおよびアンマーシャラは、指定したメディア・タイプを自動的に使用します。

例16-3のとおり、MarshallerProperties、UnmarshallerPropertiesおよびMediaType定数を使用して、アプリケーションでJSONドキュメントを使用するよう構成できます。

例16-3 MarshallerPropertiesとUnarshallerPropertiesの使用

import org.eclipse.persistence.jaxb.MarshallerProperties;
import org.eclipse.persistence.jaxb.UnarshallerProperties;
import org.eclipse.persistence.oxm.MediaType;

m.setProperty(MarshallerProperties.MEDIA_TYPE, MediaType.APPLICATION_JSON);
u.setProperty(UnmarshallerProperties.MEDIA_TYPE, MediaType.APPLICATION_JSON);
...

16.2.2 タスク2: JSONバインディングの指定

例16-4では、JAXBの標準的な使用で必要な以外の、コンパイル時の依存関係を必要としない基本的なJSONのバインディングを示します。この例では、JSONをStreamSourceからユーザー・オブジェクトSearchResultsにアンマーシャルし、コレクションに新しいResultを追加し、新しいコレクションをSystem.outにマーシャルする方法を説明します。

例16-4 基本のJSONバインディングの使用

package org.example;

import org.example.model.Result;
import org.example.model.SearchResults;

import java.util.Date;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;

public class Demo {

public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(SearchResults.class);

Unmarshaller unmarshaller = jc.createUnmarshaller();
unmarshaller.setProperty("eclipselink.media-type", "application/json");
StreamSource source = new StreamSource("http://search.twitter.com/search.json?q=jaxb");
JAXBElement<SearchResults> jaxbElement = unmarshaller.unmarshal(source, SearchResults.class);

Result result = new Result();
result.setCreatedAt(new Date());
result.setFromUser("bsmith");
result.setText("You can now use EclipseLink JAXB (MOXy) with JSON :)");
jaxbElement.getValue().getResults().add(result);

Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty("eclipselink.media-type", "application/json");
marshaller.marshal(jaxbElement, System.out);
}

}

また、MOXy外部バインディング・ファイルをJSONドキュメントとして記述できます。例16-5に、bindings.jsonを使用し、JSONにCustomerおよびPhoneNumberクラスをマップする方法を説明します。

例16-5 外部バインディングの使用

{
"package-name" : "org.example",
"xml-schema" : {
"element-form-default" : "QUALIFIED",
"namespace" : "http://www.example.com/customer"
},
"java-types" : {
"java-type" : [ {
"name" : "Customer",
"xml-type" : {
"prop-order" : "firstName lastName address phoneNumbers"
},
"xml-root-element" : {},
"java-attributes" : {
"xml-element" : [
{"java-attribute" : "firstName","name" : "first-name"},
{"java-attribute" : "lastName", "name" : "last-name"},
{"java-attribute" : "phoneNumbers","name" : "phone-number"}
]
}
}, {
"name" : "PhoneNumber",
"java-attributes" : {
"xml-attribute" : [
{"java-attribute" : "type"}
],
"xml-value" : [
{"java-attribute" : "number"}
]
}
} ]
}
}

例16-6にJAXBContextをブートストラップする際に、JSONファイル(例16-5で作成)を使用する方法を説明します。

例16-6 JAXBContextのブートストラップでのJSONの使用

Map<String, Object> properties = new HashMap<String, Object>(2);
properties.put("eclipselink.oxm.metadata-source", "org/example/binding.json");
properties.put("eclipselink.media-type", "application/json");
JAXBContext context = JAXBContext.newInstance("org.example", Customer.class.getClassLoader() , properties);

Unmarshaller unmarshaller = context.createUnmarshaller();
StreamSource json = new StreamSource(new File("src/org/example/input.json"));
...

16.2.3 タスク3: JSONデータ型の指定

XMLにはデータ型は1つしかありませんが、JSONでは文字列、数字、ブールを区別します。EclipseLinkでは、例16-7のとおりこれらのデータ型を自動的にサポートします。

例16-7 JSONデータ型の使用

public class Address {

private int id;
private String city;
private boolean isMailingAddress;

}

{
"id" : 1,
"city" : "Ottawa",
"isMailingAddress" : true
}

16.2.4 タスク4: 属性のサポート

JSONでは属性は使用せず、@XmlAttribute注釈でマップされたものをすべて、要素としてマーシャルします。EclipseLinkは、デフォルトで属性および要素イベントを両方トリガーするので、マップされた属性または要素のいずれかが値を処理できるようになります。

この動作は、例16-8のとおり、JSON_ATTRIBUTE_PREFIXプロパティを使用し、属性の接頭辞を指定することによってオーバーライドできます。EclipseLinkでは、マーシャル時に属性名に接頭辞を追加し、アンマーシャル時にそれを認識します。

次の例では、numberフィールドが接頭辞@とともに属性としてマップされます。

例16-8 接頭辞の使用

jsonUnmarshaller.setProperty(UnmarshallerProperties.JSON_ATTRIBUTE_PREFIX, "@");
jsonMarshaller.setProperty(MarshallerProperties.JSON_ATTRIBUTE_PREFIX, "@") ;

{
"phone" : {
"area-code" : "613",
"@number" : "1234567"
}
}

また、例16-9のとおり、JAXBContextの作成時にMapでJSON_ATTRIBUTE_PREFIXプロパティを設定することも可能です。このコンテキストで作成されるすべてのマーシャラおよびアンマーシャラでは、指定した接頭辞が使用されます。

例16-9 Mapでの接頭辞の設定

Map<String, Object> properties = new HashMap<String, Object>();
properties.put(JAXBContextProperties.JSON_ATTRIBUTE_PREFIX, "@");

JAXBContext ctx = JAXBContext.newInstance(new Class[] { Phone.class }, properties);

16.2.5 タスク5: ルート要素の非サポート

EclipseLinkでは、ルート要素のないJSONドキュメントをサポートしています。デフォルトでは、@XmlRootElement注釈が全く存在しない場合、マーシャルされたJSONドキュメントにはルート要素がありません。この動作は、例16-10のとおり、ドキュメントのマーシャル時に(@XmlRootElementが指定されている場合もJSONの出力からルート要素を省くこと)JSON_INCLUDE_ROOTプロパティを設定することによってオーバーライドできます。

例16-10 ルート要素のないドキュメントのマーシャル

marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);

ルート要素のないドキュメントをアンマーシャルする場合、例16-11のとおり、アンマーシャルするクラスを指定する必要があります。

例16-11 ルート要素のないドキュメントのアンマーシャル

unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
JAXBElement<SearchResults> jaxbElement = unmarshaller.unmarshal(source, SearchResults.class);

注意:

ドキュメントにルート要素がない場合は、アンマーシャルするクラスを指定する必要があります。

16.2.6 タスク5 名前空間の使用

JSONでは名前空間を使用しないので、デフォルトではすべての名前空間および接頭辞はマーシャル時およびアンマーシャル時に無視されます。同じローカル名でマッピングが複数ある場合、マッピングを区別する方法がないので、場合によってはこれが問題になることがあります。

EclipseLinkでは、接頭辞を付ける名前空間のMap(またはNamespacePrefixMapperのインスタンス)をマーシャラおよびアンマーシャラに提供できます。名前空間の接頭辞は、要素名が付加されマーシャルされたドキュメントに表示されます。EclipseLinkでは、アンマーシャル時に接頭辞を認識し、結果のJavaオブジェクトが正しい名前空間に配置されます。

例16-12に、NAMESPACE_PREFIX_MAPPERプロパティの使用方法を示します。

例16-12 名前空間の使用

Map<String, String> namespaces = new HashMap<String, String>();
namespaces.put("namespace1", "ns1");
namespaces.put("namespace2", "ns2");
jsonMarshaller.setProperty(MarshallerProperties.NAMESPACE_PREFIX_MAPPER, namespaces);
jsonUnmarshaller.setProperty(UnmarshallerProperties.JSON_NAMESPACE_PREFIX_MAPPER, namespaces);

MarshallerProperties.NAMESPACE_PREFIX_MAPPERは、XMLとJSONの両方にあり、UnmarshallerProperties.JSON_NAMESPACE_PREFIX_MAPPERはJSONのみのプロパティです。XMLのアンマーシャルでは、ドキュメントから名前空間の情報が直接取得されます。

JSONがマーシャルされると、名前空間はドット( . )で区切られた接頭辞をMapより取得します。

{
"ns1.employee : {
"ns2.id" : 123
}
}

ドットのセパレータは、JSON_NAMESPACE_SEPARATORプロパティを使用して任意のカスタム文字に設定できます。ここではかわりにコロンを使用します( : )。

jsonMarshaller.setProperty(MarshallerProperties.JSON_NAMESPACE_SEPARATOR, ':');
jsonUnmarshaller.setProperty(UnmarshallerProperties.JSON_NAMESPACE_SEPARATOR, ':');

16.2.7 タスク6: コレクションの使用

JSONにマーシャルする際に、例16-13のとおり、EclipseLinkはデフォルトで空のコレクションを[ ]としてマーシャルします。

例16-13 空のコレクションのマーシャリング

{
"phone" : {
"myList" : [ ]
}
}

この動作をオーバーライド(空のコレクションに対しマーシャルをまったく行わないように)するには、JSON_MARSHAL_EMPTY_COLLECTIONSプロパティを使用します。

jsonMarshaller.setProperty(MarshallerProperties.JSON_MARSHAL_EMPTY_COLLECTIONS, Boolean.FALSE) ;

{
"phone" : {
}
}

16.2.8 タスク7: ルートレベル・コレクションのマッピング

@XmlRootElement(name="root")注釈を使用しルート・レベルを指定した場合、JSONドキュメントは次のようにマーシャルされます。

marshaller.marshal(myListOfRoots, System.out);

[ {
"root" : {
"name" : "aaa"
}
}, {
"root" : {
"name" : "bbb"
}
} ]

このドキュメントにはルート要素があるため、次を使用してアンマーシャルできます。

unmarshaller.unmarshal(json);

クラスに@XmlRootElementがない場合(または、JSON_INCLUDE_ROOT = falseの場合)、マーシャルによって次が生成されます。

[ {
"name":"aaa"
}, {
"name":"bbb"
} ]

ルート要素が存在しないので、アンマーシャルするクラスを指定する必要があります。

unmarshaller.unmarshal(json, Root.class);

16.2.9 タスク8: テキスト値のラッピング

JAXBでは、例16-14のとおり、@XmlValueクラスで1つ以上の@XmlAttributesをサポートしています。

例16-14 @XmlAttributesの使用

public class Phone {

@XmlValue
public String number;

@XmlAttribute
public String areaCode;

public Phone() {
this("", "");
}

public Phone(String num, String code) {
this.number = num;
this.areaCode = code;
}

}

有効なJSONドキュメントを生成するために、EclipseLinkでは例16-15に示すvalueのラッパーを使用します。

例16-15 valueラッパーの使用

{
"employee" : {
"name" : "Bob Smith",
"mainPhone" : {
"areaCode" : "613",
"value" : "555-5555"
},
"otherPhones" : [ {
"areaCode" : "613",
"value" : "123-1234"
}, {
"areaCode" : "613",
"value" : "345-3456"
} ]
}
}

デフォルトでEclipseLinkは、ラッパー名としてvalueを使用します。値ラッパー名をカスタマイズするには、例16-16のとおり、JSON_VALUE_WRAPPERプロパティを使用します。

例16-16 Valueラッパー名のカスタマイズ

jsonMarshaller.setProperty(MarshallerProperties.JSON_VALUE_WRAPPER, "$");
jsonUnmarshaller.setProperty(UnmarshallerProperties.JSON_VALUE_WRAPPER, "$");

次が生成されます。

{
"employee" : {
"name" : "Bob Smith",
"mainPhone" : {
"areaCode" : "613",
"$" : "555-5555"
},
"otherPhones" : [ {
"areaCode" : "613",
"$" : "123-1234"
}, {
"areaCode" : "613",
"$" : "345-3456"
} ]
}
}

また、例16-17のとおり、JAXBContextの作成時、使用しているプロパティのMapにJSON_VALUE_WRAPPERプロパティを指定することもできます。

例16-17 Mapの使用

Map<String, Object> properties = new HashMap<String, Object>();
properties.put(JAXBContextProperties.JSON_VALUE_WRAPPER, "$");

JAXBContext ctx = JAXBContext.newInstance(new Class[] { Employee.class }, properties);
Marshaller jsonMarshaller = ctx.createMarshaller();
Unmarshaller jsonUnmarshaller = ctx.createUnmarshaller();

Mapに指定すると、JAXBContentから作成されたマーシャラおよびアンマーシャラは、指定した値ラッパーを自動的に使用します。

16.3 その他の参考資料

この章のソリューションが実装されているその他のテクノロジおよびツールの詳細は、次の参考資料を参照してください。

- Oracle TopLinkによるJAXBアプリケーションの開発

17 コンテナ外部のJPAのテスト

Oracle TopLinkでは、永続性ユニットのJARファイルを使用して、コンテナの外のアプリケーション(たとえば、Java Platform, Standard Edition (Java SEプラットフォーム)のアプリケーション)をテストできます。

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

- 17.1項「JPAデプロイメントの理解」

- 17.2項「persistence.xmlファイルの構成」

- 17.3項「プロパティ・マップの使用」

- 17.4項「ウィービングの使用」

- 17.5項「その他の参考資料」

ユース・ケース

ユーザーがTopLinkを、(Java SEプラットフォームのアプリケーションなどの)コンテナの内外の両方で使用する必要があります。

解決方法

このソリューションでは、コンテナ外部でTopLinkを使用した場合の主な違いに焦点を当てています。

コンポーネント

- TopLink 12cリリース1 (12.1.2)以上。

注意:

TopLinkのコア機能は、オープン・ソースのEclipse Foundationの永続性フレームワークであるEclipseLinkによって提供されています。EclipseLinkでは、Java Persistence API (JPA)、Java Architecture for XML Binding (JAXB)、および標準に基づいたその他の永続性テクノロジと、それらの標準の拡張が実装されます。TopLinkには、EclipseLinkのすべてに加え、Oracleの追加機能が含まれています。

- (Oracle WebLogic Server、IBM WebSphereまたはGlassfishなどの)アプリケーション・サーバー

17.1 JPAデプロイメントの理解

コンテナの外部にデプロイする場合は、javax.persistence.PersistenceクラスのcreateEntityManagerFactoryメソッドを使用して、エンティティ・マネージャ・ファクトリを作成します。このメソッドは、プロパティのMapおよび永続性ユニットの名前を受け入れます。このメソッドに渡すプロパティは、persistence.xmlファイル指定されているプロパティと組み合されます。追加のプロパティの場合もあれば、persistence.xmlファイルに以前に指定したプロパティの値をオーバーライドする場合もあります。

ヒント:

これは、コマンドラインなどのプログラム入力から取得したプロパティを設定する便利な方法です。

17.1.1 EntityManagerの使用

EntityManagerは、エンティティBeanを永続化したり、データベースからロードしたりするためのアクセス・ポイントです。通常は、Java Persistence API (JPA)コンテナで、データ・ソースとの通信が管理されます。ただし、JPA永続性ユニットに対してJTAデータ・ソースを使用している場合は、Java EEプログラムのコンテナのデータ・ソースからJDBC接続にアクセスできます。管理データ・ソースは使用できないので、プロパティをcreateEntityManagerFactoryに渡して、トランザクションの種類をJTAからRESOURCE_LOCALに変更して、次のようにJDBC接続情報を定義します。

例17-1 トランザクションの種類の変更および接続情報の定義

import static org.eclipse.persistence.jpa.config.PersistenceUnitProperties.*;

...

Map properties = new HashMap();

// Ensure RESOURCE_LOCAL transactions is used.
properties.put(TRANSACTION_TYPE,
PersistenceUnitTransactionType.RESOURCE_LOCAL.name());

// Configure the internal EclipseLink connection pool
properties.put(JDBC_DRIVER, "oracle.jdbc.OracleDriver");
properties.put(JDBC_URL, "jdbc:oracle:thin:@localhost:1521:ORCL");
properties.put(JDBC_USER, "user-name");
properties.put(JDBC_PASSWORD, "password");
properties.put(JDBC_READ_CONNECTIONS_MIN, "1");
properties.put(JDBC_WRITE_CONNECTIONS_MIN, "1");

// Configure logging. FINE ensures all SQL is shown
properties.put(LOGGING_LEVEL, "FINE");

// Ensure that no server-platform is configured
properties.put(TARGET_SERVER, TargetServer.None);

EntityManagerへのEclipseLinkの拡張へアクセスすることも可能です。

17.2 persistence.xmlファイルの構成

persistence.xmlファイルは、JPAを使用した永続性のためのデプロイメント・ディスクリプタ・ファイルです。ここには、永続性ユニットを指定し、管理対象永続性クラス、オブジェクト/リレーション・マッピング、およびデータベース接続の詳細を宣言します。

17.2.1 主なタスク

persistence.xmlファイルを構成するには、次の手順を実行します。

- タスク1: persistence.xmlファイルの使用

- タスク2: EntityManagerFactoryのインスタンス化

17.2.1.1 タスク1: persistence.xmlファイルの使用

例17-2に、Java SEプラットフォーム構成(つまり、コンテナの外部)用のpersistence.xmlファイルを示します。

例17-2 Java SE構成を指定するpersistence.xmlファイル

<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence persistence_1_0.xsd" version="1.0">
<persistence-unit name="my-app" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.jdbc.driver" value="oracle.jdbc.OracleDriver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:@localhost:1521:orcl"/>
<property name="javax.persistence.jdbc.user" value="scott"/>
<property name="javax.persistence.jdbc.password" value="tiger"/>
</properties>
</persistence-unit>
</persistence>

17.2.1.2 タスク2: EntityManagerFactoryのインスタンス化

EntityManagerFactoryを使用すれば、データベースのEntityManagerインスタンスを効率的に作成できます。次の方法を使用して、(例17-2に示す)アプリケーションのEntityManagerFactoryをインスタンス化できます。

Persistence.createEntityManagerFactory("my-app");

17.3 プロパティ・マップの使用

プロパティ・マップを使用すると、デフォルトの永続性プロパティをオーバーライドしてコンテナ・デプロイメントを使用できます。

17.3.1 主なタスク

プロパティ・マップを使用するには、次の手順を実行します。

- タスク1: persistence.xmlファイルの構成

- タスク2: ブートストラップAPIの構成

- タスク3: EntityManagerFactoryのインスタンス化

17.3.1.1 タスク1: persistence.xmlファイルの構成

例17-3に、コンテナ・デプロイメントを使用するpersistence.xmlファイルを示します。

例17-3 プロパティ・マップで使用するための、Java SE構成を指定するpersistence.xmlファイル

<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence persistence_1_0.xsd" version="1.0">
<persistence-unit name="employee" transaction-type="RESOURCE_LOCAL">
<non-jta-data-source>jdbc/MyDS</non-jta-data-source>
</persistence-unit>
</persistence>

注意:

コンテナの外でテストする際に、データ・ソースは使用できません。

17.3.1.2 タスク2: ブートストラップAPIの構成

例17-3に示されている永続性ユニットをコンテナの外でテストするには、Java SEプラットフォームのブートストラップAPIを使用する必要があります。例17-4に、このブートストラップを示すサンプル・コードを示します。

例17-4 サンプル構成

import static org.eclipse.persistence.config.PersistenceUnitProperties.*;

...

Map properties = new HashMap();

// Ensure RESOURCE_LOCAL transactions is used.
properties.put(TRANSACTION_TYPE,
PersistenceUnitTransactionType.RESOURCE_LOCAL.name());

// Configure the internal connection pool
properties.put(JDBC_DRIVER, "oracle.jdbc.OracleDriver");
properties.put(JDBC_URL, "jdbc:oracle:thin:@localhost:1521:ORCL");
properties.put(JDBC_USER, "scott");
properties.put(JDBC_PASSWORD, "tiger");

// Configure logging. FINE ensures all SQL is shown
properties.put(LOGGING_LEVEL, "FINE");
properties.put(LOGGING_TIMESTAMP, "false");
properties.put(LOGGING_THREAD, "false");
properties.put(LOGGING_SESSION, "false");

// Ensure that no server-platform is configured
properties.put(TARGET_SERVER, TargetServer.None);

17.3.1.3 タスク3: EntityManagerFactoryのインスタンス化

EntityManagerFactoryを使用すれば、データベースのEntityManagerインスタンスを効率的に作成できます。次の方法を使用して、(例17-4に示す)アプリケーションのEntityManagerFactoryをインスタンス化できます。

Persistence.
createEntityManagerFactory("unitName", "properties");

17.4 ウィービングの使用

ウィービングは、コンパイル済のJavaクラスのバイトコードを操作する方法です。

EclipseLinkでは、遅延ロード、変更追跡、フェッチ・グループ、内部最適化など多くの機能にウィービングを使用し、Plain Old Java Object (POJO)クラスとJavaエンティティを拡張しています。

17.4.1 Java SE環境でのウィービングの無効化および有効化

Java SE環境では、デフォルトでウィービングは無効です。これは、遅延1対1、多対1および基本のリレーションシップに影響を与える場合があります。また、パフォーマンスおよび属性変更トラッキングにも大きな影響があります。

Java SEでウィービングを有効にするには、Java VMの起動時にEclipseLinkエージェントを使用する必要があります。

java -javaagent:eclipselink.jar

Java SEでJPAウィービングを許可するには、Springを使用することも可能です。詳細は、http://wiki.eclipse.org/EclipseLink/Examples/JPA/JPASpringを参照してください。

次の永続性プロパティを含めることにより、静的なウィービングを使用することも可能です。

<property name="eclipselink.weaving" value="static"/>

詳細は、『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』のウィービングに関する項を参照してください。

17.4.2 Java EE環境でのウィービングの無効化および有効化

Java EE環境では、デフォルトで(すべてのJava EE 5、またはWebLogic、WebSphereおよびGlassfishなどの大規模な完全対応のアプリケーション・サーバーで)ウィービングが有効です。(JBossではウィービングを許可しないので、静的ウィービングまたはSpringを使用する必要があります)。

ウィービングを無効にするには、ウィービング永続性ユニット・プロパティを使用します。

<property name="eclipselink.weaving" value="false">

ウィービングの詳細は、『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』のウィービングに関する項を参照してください。

17.5 その他の参考資料

JPAデプロイメントの詳細は、JPA仕様の次の項(http://jcp.org/en/jsr/detail?id=317)を参照してください。

- 7.2項「Bootstrapping in Java SE Environments」

- 第7章「Container and Provider Contracts for Deployment and Bootstrapping」

17.5.1 関連Javadoc

詳細は、『Oracle TopLink Java APIリファレンス』で次のAPIを参照してください。

- PersistenceUnitPropertiesクラス

- EntityManagerFactoryインタフェース

- JpaEntityManagerインタフェース

18 パフォーマンスの向上

この章では、EclipseLinkが提供するOracle TopLinkのパフォーマンス機能、およびEclipseLinkが有効なアプリケーションの監視および最適化方法を説明します。

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

- 18.1項「パフォーマンス機能」

- 18.2項「EclipseLinkが有効なアプリケーションの監視および有効化」

ユース・ケース

TopLinkが有効なアプリケーションのパフォーマンスを向上させたいとユーザーが考えています。

解決方法

TopLinkには、キャッシュなど、パフォーマンスを向上させる多数のオプションがあります。また、問合せで結合フェッチを使用するなど、特定の機能のパフォーマンスを向上させる方法があります。

コンポーネント

- TopLink 12cリリース1 (12.1.2)以上。

注意:

TopLinkのコア機能は、オープン・ソースのEclipse Foundationの永続性フレームワークであるEclipseLinkによって提供されています。EclipseLinkでは、Java Persistence API (JPA)、Java Architecture for XML Binding (JAXB)、および標準に基づいたその他の永続性テクノロジと、それらの標準の拡張が実装されます。TopLinkには、EclipseLinkのすべてに加え、Oracleの追加機能が含まれています。

例

関連情報については、次のEclipseLinkの例を参照してください。

- http://wiki.eclipse.org/EclipseLink/Performance

- http://wiki.eclipse.org/EclipseLink/Examples/JPA/Performance

- http://wiki.eclipse.org/EclipseLink/Examples/JPA/Monitoring

18.1 パフォーマンス機能

EclipseLinkには、EclipseLinkを業界で最高のパフォーマンスと最高のスケーラビリティを備えたJPA実装にする、多くのパフォーマンス機能が含まれています。次の機能が含まれています。

- オブジェクト・キャッシング

- 問合せ

- マッピング

- トランザクション

- データベース

- ツール

18.1.1 オブジェクト・キャッシング

EclipseLinkキャッシュは、クラスと主キーの値に基づいて最近読み取られたり書き込まれたオブジェクトがストアされる、インメモリー・リポジトリです。キャッシュは、最近の読取りまたは書込みオブジェクトを保持し、メモリー内でそれらにアクセスしてデータベースへのアクセスを最小限にすることで、パフォーマンスの向上を助けます。

キャッシングでは、次のことを行えます。

- キャッシュの無効化と呼ばれるプロセスで、キャッシュの存続期間および時間を設定できます。

- キャッシュ・タイプ(Weak、Soft、SoftCache、HardCache、Full)をエンティティごとに構成できます。

- エンティティごとにキャッシュ・サイズを構成できます。

- クラスタ化されたキャッシュを調整できます。

18.1.1.1 キャッシング注釈

EclipseLinkには、次のエンティティ・キャッシング注釈が定義されています。

- @Cache

- @TimeOfDay

- @ExistenceChecking

EclipseLinkには、EclipseLinkキャッシュの構成に指定できる永続性ユニット・プロパティも多数用意されています(『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』の永続性プロパティの拡張のリファレンスに関する項を参照してください)。これらのプロパティを注釈のかわりに使用したり、注釈を補完したりできる場合があります。

18.1.1.2 @Cache注釈の使用

EclipseLinkでは、パフォーマンスを向上させ、オブジェクトIDを維持するアイデンティティ・マップを使用して、オブジェクトをキャッシュします。エンティティ・クラスで@Cache注釈を使用すれば、キャッシュおよびその動作を制御できます。例18-1に、この注釈の実装方法を示します。

例18-1 @Cache注釈の使用

@Entity
@Table(name="EMPLOYEE")
@Cache (
type=CacheType.WEAK,
isolated=false,
expiry=600000,
alwaysRefresh=true,
disableHits=true,
coordinationType=INVALIDATE_CHANGED_OBJECTS
)
public class Employee implements Serializable {
...
}

オブジェクト・キャッシュおよび@Cache注釈の使用方法の詳細は、『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』のキャッシュに関する項を参照してください。

18.1.2 問合せ

問合せの範囲、返されるデータ量、およびデータが返される方法はすべて、EclipseLinkが有効になっているアプリケーションのパフォーマンスに影響を与える可能性があります。EclipseLinkの問合せメカニズムでは、次の機能を提供して問合せパフォーマンスを向上しています。

- 読取り専用問合せ

- 結合フェッチ

- バッチ読取り

- フェッチ・サイズ

- ページ区切り

- キャッシュの使用方法

この項では、これらの機能により、どのようにパフォーマンスが向上するかを説明します。

18.1.2.1 読取り専用問合せ

EclipseLinkでは、eclipselink.read-onlyヒント、QueryHint (@QueryHint)を使用して、読取り専用の結果を問合せから取得します。リクエストされたエンティティ・タイプが共有キャッシュにストアされるような非トランザクションの読取り操作の場合は、デタッチされたコピーではなく、共有インスタンスが返されるようにリクエストできます。

読取り専用の問合せの詳細は、『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』の読取りのヒントに関するドキュメントを参照してください。

18.1.2.2 結合フェッチ

結合フェッチでは、ソース・オブジェクトと同じ問合せにある関連オブジェクトの結合および読取りを有効にすることにより、パフォーマンスを向上します。例18-2に示すように、@JoinFetch注釈を使用して、結合フェッチを有効にします。この例では、EmployeeフィールドmanagedEmployeesを@JoinFetch注釈で指定する方法を示しています。

例18-2 結合フェッチの有効化

@Entity
public class Employee implements Serializable {
...
@OneToMany(cascade=ALL, mappedBy="owner")
@JoinFetch(value=OUTER)
public Collection<Employee> getManagedEmployees() {
return managedEmployees;
}
...
}

結合フェッチの詳細は、『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』の@JoinFetchに関する項を参照してください。

18.1.2.3 バッチ読取り

eclipselink.batchヒントは、EclipseLinkにバッチ処理情報を提供して、関連オブジェクトに対する後続の問合せでオブジェクトを1つずつ取得したり、大規模な1つの結合読取りとして取得せずに、それをバッチ内で最適化できます。バッチ読取りでは、重複データの読取りが回避されるので、結合よりも効率的です。バッチ処理は、SELECT句にオブジェクトが1つしかない問合せに対してのみ実行できます。

18.1.2.4 フェッチ・サイズ

多数のオブジェクトを返す大規模な問合せがある場合は、選択条件を満たすために必要なデータベースのヒット数を減らすことにより、パフォーマンスを向上できます。これを行うには、eclipselink.jdbc.fetch-sizeヒントを使用します。このヒントには、より多くの行が必要になる場合(JDBCドライバのサポート・レベルに従って)に、データベースからフェッチする行数を指定します。ほとんどのJDBCドライバのデフォルト・フェッチ・サイズは10になっています。そのため、1000個のオブジェクトを読み取る場合、フェッチ・サイズを256に増やすと、問合せ結果のフェッチに要する時間が大幅に短縮される場合があります。最適なフェッチ・サイズが常に明白であるとはかぎりません。通常は、予想される総結果サイズの半分または4分の1がフェッチ・サイズとして最適です。結果セットのサイズが不確かな場合に、誤ってフェッチ・サイズの設定を大きく、または小さくしすぎると、パフォーマンスが低下する可能性がありますので、注意してください。

18.1.2.5 ページ区切り

ページング処理が遅いと、アプリケーションの負荷が大幅に高くなる場合がありますが、EclipseLinkには次のようなページング結果が向上する様々な解決策が用意されています。

- 問合せの実行時に最初に取得する行数および最大行数を構成できます。

- 基準と一致するすべてのID値に対してデータベースで問合せを実行してから、ID値を使用して特定のセットを取得できます。

- 問合せヒントを使用して、ScrollableCursorオブジェクトを問合せから返すようにEclipseLinkを構成できます。これにより、問合せの結果セットにデータベース・カーソルが返されるので、クライアントでページごとに結果をスクロールできるようになります。

ページング・パフォーマンスの向上の詳細は、次のEclipseLinkオンライン・ドキュメントの『How to use EclipseLink Pagination』を参照してください。

http://wiki.eclipse.org/EclipseLink/Examples/JPA/Pagination#How_to_use_EclipseLink_Pagination

18.1.2.6 キャッシュの使用方法

EclipseLinkでは、永続性ユニット全体を範囲とする共有キャッシュ・メカニズムを使用しています。特定の永続性コンテキストで操作が完了すると、結果が共有キャッシュに再びマージされて、他の永続性コンテキストが使用できるようになります。これは、エンティティ・マネージャおよび永続性コンテキストがJava SEまたはJava EEで作成されているかどうかに関係なく行われます。エンティティ・マネージャを使用して永続化または削除されたエンティティでは、常にキャッシュとの整合性が保たれます。

eclipselink.cache-usageヒントを使用すれば、問合せとEclipseLinkキャッシュがどのようにやり取りを行うかの方法を指定できます。詳細は、『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』のキャッシュの使用方法に関する項を参照してください。

18.1.3 マッピング

マッピング・パフォーマンスは次の機能で拡張されています。

- 読取り専用オブジェクト

- ウィービング

この項では、これらの機能を説明します。

18.1.3.1 読取り専用オブジェクト

クラスを読取り専用に宣言すると、そのクラスのクローンの作成もマージも行われないので、パフォーマンスが大幅に向上します。addReadOnlyClass()を使用すれば、作業ユニットのコンテキスト内でクラスを読取り専用として宣言できます。

- 単一の作業ユニットに対して読取り専用クラスを構成するには、そのクラスをaddReadOnlyClass()の引数として指定します。

myUnitofWork.addReadOnlyClass(B.class);

- 複数のクラスを読取り専用に構成するには、それらのクラスをベクトルに追加して、そのベクトルをaddReadOnlyClass()の引数として指定します。

myUnitOfWork.addReadOnlyClasses(myVectorOfClasses);

パフォーマンスを向上させるための読取り専用オブジェクトの使用方法の詳細は、『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』の@ReadOnlyに関する項を参照してください。

18.1.3.2 ウィービング

ウィービングは、コンパイル済のJavaクラスのバイトコードを操作する方法です。EclipseLink JPA永続性プロバイダでは、ウィービングを使用して、遅延ロード、変更追跡、フェッチ・グループ、内部最適化などに対して、JPAエンティティとPlain Old Java Object (POJO)クラスの両方を拡張します。ウィービングは、実行時の動的実行、エンティティのロード時の実行、エンティティの.classファイルの後処理によるコンパイル時の静的実行のいずれかで実行できます。EclipseLinkのデフォルトでは、可能な場合は常に動的ウィービングが使用されます。これは、EclipseLinkエージェントが構成されている場合のJava EE 5/6アプリケーション・サーバーおよびJava SEが含まれます。動的ウィービングは構成しやすく、プロジェクトのビルド・プロセスを変更する必要がないので、動的ウィービングをお薦めします。

アプリケーションのパフォーマンスを向上させるためにウィービングを使用する方法の詳細は、『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』のウィービングに関する項を参照してください。

18.1.4 トランザクション

データ・トランザクション時のパフォーマンスを最適化するには、変更追跡を使用します。変更追跡では、トランザクション中に発生した変更をEclipseLinkが検出する方法をチューニングできます。エンティティ・タイプが異なると、アクセス・パターンも設定も異なるので、エンティティ・タイプの使用パターンおよびデータ変更パターンに基づいて戦略を選択します。

例18-3に示すように、@ChangeTracking注釈を使用して、変更追跡を有効にします。

例18-3 変更追跡の有効化

@Entity
@Table(name="EMPLOYEE")
@ChangeTracking(OBJECT) (
public class Employee implements Serializable {
...
}

変更追跡の詳細は、『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』の@ChangeTrackingに関する項を参照してください。

18.1.5 データベース

EclipseLinkのデータベース・パフォーマンス機能には、次があります。

- 接続プーリング

- パラメータ化されたSQLとSQL文のキャッシュ

- バッチ書込み

この項では、これらの機能を説明します。

18.1.5.1 接続プーリング

データ・ソースへの接続の確立には時間がかかるため、接続プールにある接続を再使用すれば、パフォーマンスを向上できます。EclipseLinkは、接続プールを使用して、サーバーおよびクライアント・セッションで使用される接続を管理および共有します。この機能により、必要な接続数が減り、アプリケーションで多くのクライアントをサポートできるようになります。

デフォルトでは、EclipseLinkセッションは内部接続プールを使用します。これらのプールでは、表示専用でデータの変更が頻繁ではないデータを読み取るアプリケーション用の読取り接続の作成を最適化できます。また、ワークベンチを使用して、デフォルト(書込み)および読取りの接続プールを構成したり、オブジェクト・アイデンティティまたは他の目的のために追加の接続プールを作成することもできます。

内部接続プールに加えて、次のいずれかのタイプの接続プールを使用するようにEclipseLinkを構成することもできます。

- 外部接続プール。外部トランザクション・コントローラ(JTA)と統合するには、このタイプの接続プールを使用する必要があります。

- デフォルト(書込み)および読取り接続プール。

- シーケンス接続プール。表順序付け(つまり、非ネイティブ順序付け)が必要なアプリケーションで、外部トランザクション・コントローラを使用している場合には、これらのタイプのプールを使用します。アプリケーション固有の接続プール。EclipseLinkの内部接続プールをセッションで使用している場合は、アプリケーションの目的に従って、これらの接続プールを作成して使用できます。

EclipseLinkで接続プールを使用する方法の詳細は、『Oracle TopLinkの理解』の次のトピックを参照してください。

- 「接続の理解」

- 「接続プールの理解」

18.1.5.2 パラメータ化されたSQLとSQL文のキャッシュ

パラメータ化されたSQLを使用すれば、SQL問合せの全体の長さが、JDBCドライバまたはデータベース・サーバーで決められた文の長さ制限を超えることを防げます。パラメータ化されたSQLをプリコンパイル文のキャッシュとともに使用すると、コール頻度の高い問合せのSQLがデータベースのSQLエンジンによって解析およびプリコンパイルされる回数が減少し、パフォーマンスが向上します。

デフォルトでは、EclipseLinkはパラメータ使用のSQLは有効にしますが、プリコンパイルされたSQL文のキャッシュは有効にしません。内部接続プールの使用時はEclipseLinkで、外部接続プールの使用時はデータ・ソースで、文のキャッシュを有効にし、アプリケーションに適した文のキャッシュ・サイズを指定する必要があります。

パラメータ化されたSQLを有効にするには、ドメイン・クラスと同じパスにあるpersistence.xmlファイルに次の行を追加します。

<property name="eclipselink.jdbc.bind-parameters" value="true"/>

パラメータ化されたSQLを無効にするには、value=をfalseに変更します。

パラメータ化されたSQLおよび文のキャッシュの使用方法の詳細は、『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』のjdbc.bind-parametersに関する項を参照してください。

18.1.5.3 バッチ書込み

バッチ書込みは、複数の書込み操作があるトランザクションの最適化に役立ちます。バッチ書込みは、EclipseLinkのJDBC拡張機能のbatch-writingを使用して有効にします。デプロイ時に、次のパラメータのいずれかを、セッションのこのプロパティに設定してください。

- JDBC: JDBCのバッチ書込みを使用します。

- Buffered: JDBCのバッチ書込みもネイティブ・プラットフォームのバッチ書込みも使用しません。

- Oracle-JDBC: JDBCのバッチ書込みとOracleネイティブ・プラットフォームのバッチ書込みの両方を使用し、プロパティ・マップでOracleJDBCを使用します。

- None: バッチ書込みを無効にします。

バッチ書込みの詳細は、『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』のjdbc.batch-writingに関する項を参照してください。

18.1.6 ツール

18.2項「EclipseLinkが有効なアプリケーションの監視および最適化」に説明されているように、EclipseLinkには監視ツールと最適化ツールが用意されています。

18.2 EclipseLinkが有効なアプリケーションを監視および最適化

パフォーマンス・チューニングにおける最も重要な課題は、最適化の対象を知ることです。アプリケーションのパフォーマンスを向上させるには、アプリケーションの中で稼働時の効率が最大に達していない領域を特定します。この項では、次のことを説明します。

- パフォーマンス最適化の推奨事項およびヒント

- タスク1: EclipseLinkプロファイラを使用したEclipseLinkのパフォーマンスの測定

- タスク2: アプリケーションのパフォーマンス問題の原因特定

- タスク3: パフォーマンスが悪いアプリケーション・コンポーネントの変更

- タスク4: パフォーマンスの再測定

18.2.1 パフォーマンス最適化の推奨事項およびヒント

EclipseLinkには、アプリケーションのパフォーマンスを測定し、最適化するための様々な機能が用意されています。ほとんどの機能はディスクリプタまたはセッションで有効または無効にできるので、向上したパフォーマンスをグローバルに適用できます。開発サイクルのどの段階でもパフォーマンスを考慮する必要があります。これは、設計および実装作業の中でパフォーマンスの問題を認識していることを意味しますが、最初の試みで最高のパフォーマンスを達成する必要があるわけではありません。

たとえば、最適化によって設計が複雑になる場合は、最適化作業を最終的な開発フェーズに回します。それでも、後の統合が簡単になるように、最初の段階から最適化の計画を立てることは必要です。

EclipseLinkアプリケーションのチューニングに関連した最も重要な概念は、反復という考え方です。アプリケーションをチューニングする最も効果的な方法は、次のタスクを実行することです:

- タスク1: EclipseLinkプロファイラを使用したEclipseLinkのパフォーマンスの測定

- タスク2: アプリケーションのパフォーマンス問題の原因特定

- タスク3: パフォーマンスが悪いアプリケーション・コンポーネントの変更

- タスク4: パフォーマンスの再測定

18.2.2 タスク1: EclipseLinkプロファイラを使用したEclipseLinkのパフォーマンスの測定

EclipseLinkパフォーマンス・プロファイラは、指定のセッション内で実行されたすべての問合せのパフォーマンス統計をロギングすることにより、パフォーマンスの問題を識別するために役立ちます。

EclipseLinkパフォーマンス・プロファイラでは、次の情報がログ・ファイルに記録されます。

表18-1 EclipseLinkパフォーマンス・プロファイラでログに記録される情報

ログに記録される情報

説明

問合せクラス

問合せクラス名。

ドメイン・クラス

ドメイン・クラス名。

合計時間

ネストされた問合せを含む、問合せの合計実行時間(ミリ秒)。

ローカル時間

ネストされた問合せを除く、問合せの実行時間(ミリ秒)。

オブジェクト数

影響を受けたオブジェクトの合計数。

1秒当たりのオブジェクト処理数

トランザクション時に一秒当たりに処理されたオブジェクト数。

ロギング

ロギング・メッセージの出力に費やされた時間(ミリ秒)。

SQL準備

SQLスクリプトの準備に費やされた時間(ミリ秒)。

SQL実行

SQLスクリプトの実行に費やされた時間(ミリ秒)。

行フェッチ

データベースからの行のフェッチに費やされた時間(ミリ秒)

キャッシュ

オブジェクト・キャッシュの検索または更新に費やされた時間(ミリ秒)

オブジェクト・ビルド

ドメイン・オブジェクトの作成に費やされた時間(ミリ秒)

問合せ準備

実行する前に問合せの準備に費やされた時間(ミリ秒)

SQL生成

SQLスクリプトをデータベースに送信する前にSQLスクリプトの生成に費やされた時間(ミリ秒)

18.2.2.1 EclipseLinkプロファイラの有効化

EclipseLinkパフォーマンス・プロファイラは、org.eclipse.persistence.tools.profiler.PerformanceProfilerクラスのインスタンスです。有効にするには、次の行をpersistence.xmlファイルに追加します。

<property name="eclipselink.profiler" value="PerformanceProfiler.logProfiler"/>

EclipseLinkプロファイラの有効化に加えて、PerformanceProfilerクラスのパブリックAPIでも、表18-2で説明する機能が提供されています。

表18-2 PerformanceProfilerの追加機能

目的

使用するメソッド

プロファイラを無効にします。

dontLogProfile

操作統計などの各操作プロファイルのすべてのサマリーに、プロファイラがログインするように編成します。操作統計にはプロファイリングされたすべての操作の最短時間、すべての操作の合計時間、プロファイリングされた問合せによって返されたオブジェクトの数、プロファイリングされた各種操作に要した合計時間などがあります。

logProfileSummary

プロファイラ・ログを、各操作プロファイルを問合せ別にまとめたサマリーとして編成します。

logProfileSummaryByQuery

プロファイラ・ログを、各操作プロファイルをクラス別にまとめたサマリーとして編成します。

logProfileSummaryByClass

18.2.2.2 プロファイラの結果へのアクセスおよび解釈

プロファイリングの結果は、メモ帳などのテキスト・エディタでプロファイル・ログを開けば表示できます。

プロファイラ出力ファイルには、EclipseLinkが有効なアプリケーションのヘルスが示されます。

例18-4にEclipseLinkプロファイラの出力例を示します。

例18-4 パフォーマンス・プロファイラの出力

Begin Profile of{
ReadAllQuery(com.demos.employee.domain.Employee)
Profile(ReadAllQuery,# of obj=12, time=139923809,sql execute=21723809,
prepare=49523809, row fetch=39023809, time/obj=11623809,obj/sec=8)
} End Profile

例18-4に、問合せに関する次の情報を示します。

- ReadAllQuery(com.demos.employee.domain.Employee): プロファイリングした問合せとその引数

- Profile(ReadAllQuery): プロファイルの開始と問合せのタイプ

- # of obj=12: 問合せに関与したオブジェクトの数

- time=139923809: 問合せの合計実行時間(ミリ秒)

- sql execute=21723809: SQL文の実行に要した合計時間

- prepare=49523809: SQL文の準備に要した合計時間

- row fetch=39023809: データベースからの行のフェッチに要した合計時間

- time/obj=116123809: 各オブジェクトで要した時間(ナノ秒)

- obj/sec=8: 1秒当たりのオブジェクト処理数

18.2.3 タスク2: アプリケーションのパフォーマンス問題の原因特定

アプリケーションでパフォーマンスの問題が起こる可能性のある部分は、次のとおりです。

- 一般的なパフォーマンスの最適化の識別

- スキーマ

- マッピングおよびディスクリプタ

- セッション

- キャッシュ

- データ・アクセス

- 問合せ

- 作業ユニット

- アプリケーション・サーバーとデータベースの最適化

「タスク3: パフォーマンスが悪いアプリケーション・コンポーネントの変更」では、これらの各領域に対処するための簡単なガイドラインを説明します。

18.2.4 タスク3: パフォーマンスが悪いアプリケーション・コンポーネントの変更

18.2.3項「タスク2: アプリケーションのパフォーマンス問題の原因特定」に示されているアプリケーションのパフォーマンス問題の各原因に対して、この項で説明されている回避策を試みることができます。

18.2.4.1 一般的なパフォーマンスの最適化の識別

アプリケーションで必要な場合を除き、EclipseLinkのデフォルト動作をオーバーライドしないでください。これらの一部のデフォルトは、開発環境に適したものです(本番環境に合うようにするには、これらのデフォルトを変更します)。デフォルトは次などです。

- バッチ書込み: 詳細は、『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』のjdbc.batch-writingに関する項を参照してください。

- 文のキャッシュ: 詳細は、『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』のjdbc.cache-statementsに関する項を参照してください。

- 接続プール・サイズの読み書き: 『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』のconnection-poolに関する項を参照してください。

- セッション・キャッシュのサイズ: 詳細は、『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』のmaintain-cacheに関する項を参照してください。

手動でコーディングするのではなく、ワークベンチを使用してください。これらのツールは使用しやすいだけでなく、デプロイXML(および必要に応じて生成されたコード)にエクスポートされるデフォルト構成は、ほとんどのアプリケーションに対して最適化されたベスト・プラクティスを示します。

18.2.4.2 スキーマ

データベース・スキーマおよびオブジェクト・モデルを設定する際には、最適化を考慮することが重要です。パフォーマンスの問題のほとんどは、オブジェクト・モデルやデータベース・スキーマが複雑すぎて、データベースが遅く、問合せが難しい場合に発生します。これが発生する可能性が高いのは、複雑なオブジェクト・モデルからデータベース・スキーマを直接導出した場合です。

パフォーマンスを最適化するには、オブジェクト・モデルとデータベース・スキーマを一緒に設計します。ただし、各モデルを最適に設計してください。これら2つが1対1に対応する必要はありません。

スキーマを最適化する方法には、次があります。

- 2つの表を1つに集約する

- 1つの表を多数に分割する

- 折りたたまれた階層を使用する

- 多数から1つを選択する

詳細は、『Oracle TopLinkの理解』のデータ記憶域スキーマに関する項を参照してください。

18.2.4.3 マッピングおよびディスクリプタ

マッピングおよびディスクリプタにパフォーマンスのボトルネックが見つかった場合は、次の解決策を試みてください。

- 常にインダイレクション(遅延ロード)を使用します。インダイレクションは、最適化するデータベース・アクセスでクリティカルであるだけでなく、これによってキャッシュ・アクセスおよび作業ユニットの処理の最適化など、EclipseLinkでその他複数の最適化を実行できます。『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』のキャッシュの使用に関する項を参照してください。

- EclipseLinkのマッピングで、特にgetメソッドまたはsetメソッドに負荷の高い、または副次的な危険性のあるコードが存在する場合は、メソッド・アクセスを使用しないようにし、かわりにデフォルトの属性への直接アクセスを使用してください。『Oracle TopLinkの理解』のメソッドまたは直接フィールド・アクセスの使用に関する項を参照してください。

- アプリケーションで必要な場合以外は、存在チェック・オプションcheckCacheThenDatabaseをディスクリプタで使用しないようにします。デフォルトの存在チェック動作の方がパフォーマンスに優れています。『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』の@ExistenceCheckingに関する項を参照してください。

- EclipseLinkがオブジェクトのインスタンス化に使用するデフォルト・コンストラクタで、初期化に高い負荷をかけないようにします。そのかわりに、遅延初期化またはEclipseLinkのインスタンス化ポリシーを使用してディスクリプタを構成し、別のコンストラクタを使用します。『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』の@InstantiationCopyPolicyに関する項を参照してください。

18.2.4.4 キャッシュ

キャッシュを使用すると、クラスタ環境でもキャッシュ・コーディネーションを実装することにより常にパフォーマンスを向上できます。キャッシュ・コーディネーションでは、分散される可能性のある複数のセッションのインスタンスが相互にオブジェクト変更を送信できるようになるので、各セッションのキャッシュは最新の状態を保つことができます。キャッシュの動作を最適化する方法の詳細は、『Oracle TopLinkの理解』のキャッシュに関する項および次の例を参照してください。

- http://wiki.eclipse.org/EclipseLink/Examples/JPA/Caching

- http://wiki.eclipse.org/EclipseLink/Examples/JPA/CacheCoordination

- http://wiki.eclipse.org/EclipseLink/Examples/JPA/DCN

18.2.4.5 データ・アクセス

EclipseLinkでは、自分のアプリケーションからアクセスするデータ・ソースのタイプによって、低レベルのデータ読取りと書込みのパフォーマンス調整に使用できる、様々なLoginオプションを提供します。高レベルのデータの読み書きを最適化するには、アプリケーションのデータ・アクセスのパフォーマンスを向上させるテクニックがいくつか記載されている、『Oracle TopLinkの理解』のデータ・アクセスに関する項を参照してください。そこでは、次の方法が説明されています。

- JDBCドライバ・プロパティの最適化

- データ形式の最適化

- バッチ書込みを使用した最適化

- 外部結合読取りと継承先サブクラスの使用

- パラメータ化されたSQL(パラメータ・バインド)とプリコンパイルされたSQL文のキャッシュを使用した最適化

18.2.4.6 問合せ

EclipseLinkには、データの読取り、書込みおよび更新用の問合せにAPIが幅広く用意されています。アプリケーションの問合せのパフォーマンスを向上させるテクニックがいくつか記載されている、『Oracle TopLinkの理解』のEclipseLinkの問合せに関する項を参照してください。そこでは、次の方法が説明されています。

- パラメータ化されたSQLとプリコンパイルされたSQL文のキャッシュを使用した最適化

- 名前付き問合せを使用した最適化

- バッチ読取りと結合読取りを使用した最適化

- 部分オブジェクト問合せとフェッチ・グループを使用した最適化

- 読取り専用問合せを使用した最適化

- JDBCフェッチ・サイズを使用した最適化

- カーソル付きストリームとスクロール可能カーソルを使用した最適化

- 結果セットのページ区切りを使用した最適化

ここには、読取りおよび書込みの最適化の例へのリンクも示されています。

18.2.4.7 アプリケーション・サーバーとデータベースの最適化

アプリケーション・サーバーおよびデータベースのパフォーマンスを最適化するために、次の方法を検討してください。

- アプリケーション・サーバーおよびデータベースを正しく構成すると、パフォーマンスおよびスケーラビリティに大きく影響する場合があります。EclipseLinkアプリケーションおよび永続性の他に、アプリケーションのこれらの主要コンポーネントを正しく最適化していることを確認してください。

- アプリケーション・サーバーまたはJava EEサーバーの場合は、メモリー、スレッド・プール・サイズおよび接続プール・サイズが、サーバーで予測されるロードに十分であり、JVMの構成が最適であることを確認します。

- 最適なパフォーマンスと予測されるロードに対応できるように、データベースが正しく構成されていることを確認します。

18.2.5 タスク4: パフォーマンスの再測定

最後に、パフォーマンスのボトルネックになっている可能性のある場所を特定して、それらに対処した後、プロファイラを有効にしてアプリケーションを再実行します(18.2.2.1項「EclipseLinkプロファイラの有効化」を参照)。結果を検討し、さらに処置が必要な場合は、18.2.4項「タスク3: パフォーマンスが悪いアプリケーション・コンポーネントの変更」に示されている手順に従います。

19 TopLink GridでのOracle Coherenceを使用したアプリケーションのスケーリング

この章では、TopLink Gridを紹介し、これを使用して高可用性を実現し、アプリケーションをスケール・アウトする方法を説明します。TopLink Gridの使用の詳細は、「Oracle Coherenceの統合」を参照してください。

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

- 19.1項「ソリューションの概要」

- 19.2項「ソリューションの実装」

- 19.3項「その他の参考資料」

ユース・ケース

JPAアプリケーションを、要求に対応するよう、また高可用性を実現するためにスケール・アウトする必要があります。

解決方法

TopLinkとCoherenceを統合したTopLink Gridを使用してこの実装を実現します。

コンポーネント

- TopLink 12cリリース1 (12.1.2)以上。

注意:

TopLinkのコア機能は、オープン・ソースのEclipse Foundationの永続性フレームワークであるEclipseLinkによって提供されています。EclipseLinkでは、Java Persistence API (JPA)、Java Architecture for XML Binding (JAXB)、および標準に基づいたその他の永続性テクノロジと、それらの標準の拡張が実装されます。TopLinkには、EclipseLinkのすべてに加え、Oracleの追加機能が含まれています。

- TopLink Grid

- Coherence

例

サンプル・アプリケーションへのリンクは、19.3項「その他の参考資料」を参照してください。

19.1 ソリューションの概要

Oracle TopLink Gridは、EclipseLink JPAとCoherenceとの統合を可能にするOracle TopLinkの機能です。標準のJPAアプリケーションは、プライマリ・データ・ストア(一般的にリレーショナル・データベース)と直接対話します。ただし、TopLink Gridの場合、ドメイン・モデルの一部またはすべてをCoherenceデータ・グリッドに格納できます。この構成は、グリッド基盤のJPAとも呼ばれています。

TopLink Gridを構成して、Coherenceのプライマリ・データ・ストアとしての使用、グリッドに対する問合せの実行、およびCoherenceによる新規データと変更データにおける永続性の管理ができます。Coherenceでは、JPAとデータ・ストア間のレイヤーが提供されており、すべてのアプリケーション・インスタンスからデータベース・コールを直接オフロードできます。これにより、クラスタ化されたアプリケーションのデプロイメントでは、通常のデータベース操作の限界を超えるスケーラビリティが得られます

アプリケーションで使用できる一般的なTopLink Gridの構成は次のとおりです。

- グリッド・キャッシュ構成。CoherenceをTopLink L2(共有)キャッシュとして使用します。この構成では、Coherenceのキャッシュにすべて事前ロードできずデータベースでホストされるデータに依存するJPAアプリケーションにCoherenceのデータ・グリッドを適用します。事前ロードができない理由には、Coherenceのフィルタの機能セットを超える非常に複雑な問合せ、古いキャッシュの原因となるサード・パーティ製データベースによる更新、ネイティブSQL問合せ、ストアド・プロシージャやトリガーへの依存などがあります。
この構成では、ローカルL2キャッシュを調整することなく、TopLinkを大規模なクラスタにスケール・アップできます。エンティティに対する更新は、トランザクションがコミットされると即時にすべてのCoherenceクラスタ・メンバーで使用可能になります。

- グリッド・エンティティ構成。この構成は、(比較的安定した)大容量データへ高速にアクセスする必要があり、更新が比較的少ないアプリケーションに最適です。ライトビハインドを使用してこの構成をCoherenceキャッシュ・ストアと組み合せると、データベース更新を非同期に実行することにより、アプリケーションのレスポンス時間を向上させることができます。

- グリッド読取り構成。この構成は、(比較的安定した)大容量データへ高速にアクセスして変更をデータベースへ同期的に書き込む必要のあるエンティティに最適です。これらのエンティティでは、Coherenceキャッシュへの移入にキャッシュ・ウォーミングが使用されますが、各問合せは必要に応じてデータベースに送信することもできます。

19.2 ソリューションの実装

TopLink Gridの構成の完全な詳細およびTopLink Gridを使用したアプリケーション開発については、「Oracle Coherenceの統合」を参照してください。

19.3 その他の参考資料

この章のソリューションが実装されているその他のテクノロジおよびツールの詳細は、次の参考資料を参照してください。

- コード例は、次からダウンロードできます。
http://www.oracle.com/technetwork/middleware/toplink/examples-325517-en-ca.html

- Oracle® Fusion Middleware Oracle TopLink Java APIリファレンスのoracle.eclipselink.coherence.* API

20 RESTfulデータ・サービスからのJPAエンティティの公開

この章では、RESTfulデータ・サービスを使用してJPA永続性ユニットを公開する方法を説明します。

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

- 20.1項「ソリューションの概要」

- 20.2項「ソリューションの実装」

- 20.3項「その他の参考資料」

- 20.4項「RESTfulデータ・サービスのAPIリファレンス」

ユース・ケース

HTML5/JavaScriptおよびモバイル・テクノロジを含む、Thinサーバー・アーキテクチャ(TSA)クライアントを開発するために、RESTを介して永続性データ・モデルおよびアプリケーション・ロジックを公開します。

解決方法

RESTfulデータ・サービスを使用すると、JAX-RSコードを記述する必要なく、RESTfulサービスを使用するエンティティを公開できます。

コンポーネント

- 次を含むJava EEアプリケーション・サーバー

- TopLink 12cリリース1 (12.1.2)以上。

注意:

TopLinkのコア機能は、オープン・ソースのEclipse Foundationの永続性フレームワークであるEclipseLinkによって提供されています。EclipseLinkでは、Java Persistence API (JPA)、Java Architecture for XML Binding (JAXB)、および標準に基づいたその他の永続性テクノロジと、それらの標準の拡張が実装されます。TopLinkには、EclipseLinkのすべてに加え、Oracleの追加機能が含まれています。

- Jersey (http://jersey.java.net/を参照)などのJAX-RS参照の実装であるJava API for RESTful Web Services (JAX-RS) 1.0に対するサポート。

- Oracle Database、Oracle ExpressまたはMySQLなどの対応するJava Database Connectivity (JDBC)データベース

20.1 ソリューションの概要

REpresentational State Transfer (REST)は、Webサービスがリソースとみなされる分散システムのアーキテクチャの原則のセットを定義します。これらのリソースは、HTTPプロトコルを使用してアドレス指定および送信できるURIで指定します。RESTは、JPAなど、多数のテクノロジとともに使用できます。リソースにアクセスしたり操作を実行するには、HTTPメソッドを使用します。

Java API for RESTful Web Services (JAX-RS)は、RESTアーキテクチャを使用するJAVAアプリケーションの構築を容易にするために設計されたAPIです。JAX-RSでは、リソースおよびそれらのリソースに対して実行できるアクションを定義するために注釈を使用します。

RESTfulアプリケーションのJPA永続性ユニットと通信するためにJAX-RSを直接使用することも可能ですが、RESTfulデータ・サービスにはJPAの永続性にRESTを実装するのを容易にするAPIが用意されています。RESTを介して永続性ユニットを公開する単純な方法であるこのAPIを使用すると、JAX-RSコードを明示的に記述せずにJPA永続性ユニットと通信できます。

注意:

RESTfulアプリケーションにJPAの永続性を実装するために直接JAX-RSを使用する例については、http://wiki.eclipse.org/EclipseLink/Examples/REST/GettingStartedのRESTfulサービスの例に関する項を参照してください。RESTfulデータ・サービスを使用してこの手順を単純化する方法の詳細は、この章を続けて読んでください。

RESTfulデータ・サービスは、Webアプリケーションの機能を拡張するWebフラグメントを介して有効にします。このREST機能は、WebアプリケーションのWEB-INF/libフォルダにRESTfulデータ・サービスのJARファイルを含めることによって有効になります。

実行しているアプリケーションにパッケージされたすべての永続性ユニットおよびその中にプロビジョニングされている動的なすべての永続性ユニットへのアクセスは、RESTfulデータ・サービスのランタイムにより提供されます。

20.2 ソリューションの実装

この項では、RESTfulデータ・サービスを使用してJPAエンティティを公開する、次のタスクについて説明します。

- 手順1: 前提条件

- 手順2: アプリケーションの作成および構成

- 手順3: RESTfulデータ・サービスのURIの基本の理解

- 手順4: JPA、JAXBまたはJSONを使用したエンティティの表現

- 手順5: 永続性ユニットに対する操作用のクライアント呼び出しの発行

- 手順6: セキュリティの実装

- 手順7: RESTfulデータ・サービスの応答の構造の理解

20.2.1 手順1: 前提条件

RESTfulデータ・サービスを実装および使用するには、次が必要です。

- Oracle WebLogic Server 12c (12.1.2)以上(次を含む)。

- EclipseLink 2.4以上(永続性プロバイダとして構成される)

- Java API for RESTful Web Services (JAX-RS) 1.0仕様の参照実装であるJersey。

- toplink-dataservices-web.jarファイル。このファイルは、TOPLINK_HOME\oracle_common\modules\oracle.toplink_release_numの下のTopLink配布に含まれています(ここでTOPLINK_HOMEは、TopLinkをインストールした場所を指し、release_numはoracle.toplink_12.1.2などのTopLinkのリリース番号を指します)。

- Oracle Database、Oracle Database Express Edition (Oracle Database XE)またはMySQLを含む対応するすべてのJava Database Connectivity (JDBC)データベース。ここで説明する手順は、Oracle Database XE 11gリリース2のものです。
保証マトリックスについては、http://www.oracle.com/technetwork/middleware/ias/index-099524.htmlを参照してください。

20.2.2 手順2: アプリケーションの作成および構成

RESTfulデータ・サービスは、標準のJPAアプリケーションと機能するように設計されていますが、有効にするには、サービスを有効にするのみではなく、次で説明するいくつかの作業を行う必要があります。

1. 1つ以上の標準のJPA永続性ユニットを使用してアプリケーションを開発し、Web ARchive (WAR)ファイルにパッケージして、普通にデプロイします。

注意:

フラグメントはWebサービスを提供するのでWARに含める必要があります。WARはオプションでEnterprise Archive (EAR)ファイルにパッケージすることもできます。

注意:

いくつかのRESTfulデータ・サービスの機能には、リレーションシップをリンクとして提供したり、リレーションシップを編集したり、多対1の遅延リレーションシップを処理するウィービンが必要です。したがって、これらの機能が必要な場合には、Java EEに対応のサーバーにデプロイするか、クラスを静的にウィーブする必要があります。

2. アプリケーションを含むWARにRESTfulデータ・サービス・サーブレットを含めます。(ダウンロード方法の詳細は、「手順1: 前提条件」を参照してください。)

注意:

RESTfulデータ・サービスのJARファイルには、サーブレットを指定し、RESTfulサービスのルートURIを定義するweb-fragment.xmlファイルが含まれます。

toplink-dataservices-web.jarファイルを、WEB-INF/lib下のアプリケーションを含むWARに追加します。

20.2.3 手順3: RESTfulデータ・サービスのURIの基本の理解

RESTfulデータ・サービス用にREST呼び出しを行うURIは、次の標準のパターンに従っています。

- アプリケーションのベースURIは、http://server:port/application-name/persistence/{version}です。

注意:

TopLink 12.1.2のRESTfulデータ・サービスのバージョンは、v1.0で、このバージョン番号を使用してRESTfulデータ・サービスに対してRESTリクエストを行う必要があります。たとえば、現在のバージョンのRESTfulデータ・サービスを使用するアプリケーションのRESTfulデータ・サービスのベースURIは、http://localhost:8080/exampleApp/persistence/v1.0などになります。

- 永続性ユニット上のベース操作には、永続性ユニット名を追加します。
/persistence/{version}/{unit-name}

- 特定の種類の操作については、次などのように操作の種類を追加します。

- エンティティの操作: /persistence/{version}/{unit-name}/entity

- 問合せの操作: /persistence/{version}/{unit-name}/query

- 単一の結果の問合せ操作: /persistence/{version}/{unit-name}/singleResultQuery

- 永続性ユニット・レベルのメタデータ操作: /persistence/{version}/{unit-name}/metadata

- ベース操作: /persistence/{version}

これらのURIの構成方法の詳細は、20.4項「RESTfulデータ・サービスのAPIリファレンス」を参照してください。

20.2.4 手順4: JPA、JAXBまたはJSONを使用したエンティティの表現

RESTfulデータ・サービス内のエンティティは、次の2つの方法で示します。

- JPAエンティティとして: JPAエンティティをマッピングする場合、注釈を使用するかXMLファイルを使用するかの一般的なJPAの表現方法で示します。これらのマッピングは、データ・ソースとの通信に使用されます。

- JAXB/JSONとして: JAXB/JSONを使用する場合には、特定のマッピング情報は不要です。RESTfulデータ・サービスでは、デフォルトでJAXBのデフォルト(JAXB仕様に定義)が使用され、JAXB/JSONにマッピングされます。オブジェクトのマッピング方法を変更するには、オプションでクラスにJAXB注釈を加えます。また、XML定義のJAXBマッピングを指定するには、永続性ユニットのpersistence.xmlに永続性ユニット・プロパティeclipselink.jpa-rs.oxmを指定します。

20.2.4.1 リレーションシップ

JSON/JAXBを使用し情報通信を行うには、一般的にJAXBのデフォルトのマッピングで十分です。ただし、リレーションシップを扱う場合には特殊なケースがいくつかあります。

双方向リレーションシップとサイクル

双方向リレーションシップは、JPAでは一般的であり、データベースで外部キーを使用して簡単に表現できます。これをXMLや標準のJAXBを使用するJSONドキュメントで表現することは、より困難です。ただし、EclipseLinkのJAXBの実装では逆の関係を定義する方法があります。逆の関係をXMLまたはJSONに直接記述せず、XMLまたはJSONがアンマーシャリングされる際に移入します。これは、次のように処理されます。

JPAの双方向の関係の定義には、所有者側と非所有者側があります。データベースの表に外部キーがあるエンティティは、所有者側のエンティティです。もう一方の表(ポイント対象)が、逆(非所有)エンティティです。JPAマッピングのmapped-by属性で、どちらがどちらであるかを定義します。mappedBy属性は、逆サイドにある必要があります。RESTfulデータ・サービスのデフォルトでは、所有者側が逆関係です。その結果、所有者関係のオブジェクトが読み書きされると、そのリレーションシップは無視されます。

次に疑似コードの場合を考えてみましょう。

@Entity
ClassA{

@Id
int id

@OneToOne
myB

}

@Entity
ClassB{

@Id
int id

@OneToOne(mappedby="myB")
myA

}

オブジェクトの定義が次である場合

- A1 は id=1で、myB = B1

- B1 は id=11 で、myA = A1

次のJSONでは、これらのオブジェクトに対応します。

A {
id:1
}

B {
id:11
myA: {
id: 1
}
}

値渡し対参照渡し

RESTfulデータ・サービスでは、RESTリクエストでリレーションシップ・オブジェクトを値または参照として渡すことができます。JSON属性は、リソース参照(「値渡し」を参照)を保持し、_relationshipはナビゲーション・リンク(「リファレンス渡し」を参照)を持ちます。

値渡し

オブジェクトを値で渡すには、オブジェクトを示す一般的なJSONまたはXMLを作成します。次のJSONではmyAを値で渡します。

B {
id:11
myA {
id: 1
}
}

参照渡し

オブジェクトを参照渡しするには、_linkを使用します。このリンクが、そのオブジェクトを取得するために必要なRESTfulデータ・サービス呼び出しを示します。次のJSONではmyAを参照で渡します。

B {
id:11
myA {
_link:{
href: "http://localhost:8080/app/persistence/v1.0/pu/entity/A/1"
method: "GET"
rel: "self"
}
}
}

linkは、href、methodおよびrel属性で構成されます。

- href (ハイパーテキスト・リファレンス)とは、リンクされているエンティティのURIです。hrefは、リンクされているエンティティまたは属性を一意に識別します。

- methodは、hrefが使用される操作を指定します。

- relは、それを含むエンティティとそれにリンクされているエンティティ間の関係を指定します。

リストには、参照と値アイテムを混合できます。リクエストでアイテムが参照で指定されている場合、対応するエンティティが必要です(そうでない場合、RESTfulデータ・サービスによってエラーが返されます)。

次の例では、正規表現のような構文でリクエストとしてRESTfulデータ・サービスに送信できるJSONを示します。

{
"numericAttribute": 1
"stringAttribute": "auction1"
"dateAttribute": 12-09-16
"singleRelatedItem": RELATED_ITEM?
"listRelatedItem":
{
RELATED_ITEM*
}
}

RELATED_ITEM =

{
"numericAttribute": 11
"stringAttribute": "myName"
}

OR

"_link" {
"rel"="self",
"href" = "LINK_HREF",
"method"="GET"
}

次のJSONでは、Bidという直接マップされたいくつかのフィールドとエンティティの集合を持つAuctionというエンティティを示します。

{
"description": "Auction 1",
"endPrice": 0,
"id": 2,
"image": "auction1.jpg",
"name": "A1",
"sold": false,
"startPrice": 100,
"bids": [
{
"_link": {
"href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/auction/entity/Bid/5",
"method": "GET",
"rel": "self"
}
},
{
"_link": {
"href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/auction/entity/Bid/6",
"method": "GET",
"rel": "self"
}
}
]
}

XMLの表現は、JSONの表現を模倣しています。次のXMLの例では、Bidという直接マップされたいくつかの属性とエンティティのリストを持つAuctionというエンティティを示します。

<?xml version="1.0" encoding="UTF-8"?>
<Auction>
<description>Auction 1</description>
<endPrice>0.0</endPrice>
<id>2</id>
<image>auction1.jpg</image>
<name>A1</name>
<sold>false</sold>
<startPrice>100.0</startPrice>
<bids>
<_link href="http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/auction/entity/Bid/5" method="GET" rel="self" />
</bids>
<bids>
<_link href="http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/auction/entity/Bid/6" method="GET" rel="self" />
</bids>
</Auction>

20.2.5 手順5: 永続性ユニットに対する操作用のクライアント呼び出しの発行

クライアントは、デプロイしたアプリケーションの永続性ユニットで操作を行うためにHTTP呼び出しを使用します。この呼び出しを構成する要件およびオプションの詳細は、20.4項「RESTfulデータ・サービスのAPIリファレンス」を参照してください。

20.2.5.1 ヘッダー内でのメディア形式の指定

このRESTインタフェースでは、XMLおよびJSONの両方で表現されたデータを処理できます。コンテンツの形式は、呼び出し元でHTTPヘッダー値を使用して指定する必要があります。

- Content-Type = application/jsonは、コンテンツがJSONに送られることを示します。

- Content-Type = application/xmlは、コンテンツがXMLに送信されることを示します。

- Accept = application/jsonは、結果としてJSON形式が期待されることを示します。

- Accept = application/xmlは、結果としてXML形式が期待されることを示します。

ヘッダー値の指定がない場合、デフォルトでJSONが使用されます。Content-typeが指定され、Acceptが指定されない場合、返される形式は渡されたContent-typeと同じになります。

注意:

多くのRESTユーティリティでは、Accept値のデフォルト値はapplication/xmlです。このとき、JSONを希望する場合はこの値を明示的に構成する必要があります。

20.2.5.2 ロギングについて

RESTfulデータ・サービスの処理と関係するメッセージは、org.eclipse.persistence.jparsと呼ばれるロガーに記録されます。多くのメッセージは、FINEレベルで記録されます。例外スタックはFINERに記録されます。

EntityManager、EntityManagerFactoryおよびJAXBContext内の処理と関係するメッセージは、他のEclipseLinkのログと同様な方法で記録されます。

20.2.6 手順6: セキュリティの実装

RESTfulデータ・サービスは、典型的なのRESTセキュリティ・メカニズムを使用してセキュリティを確保します。

20.2.7 手順7: RESTfulデータ・サービスの応答の構造の理解

RESTfulデータ・サービスのXMLまたはJSONの応答メッセージには次のカテゴリが含まれます。

- int, double, String, Integer, Double, Booleanなどの基本データ型。

- リレーションシップ(リンクおよびリレーションシップ)

次の項では、データの各カテゴリのセマンティクおよび構文について詳細に説明します。

XMLとJSONの応答には(形式以外に)他にもいくつかの違いがあります。JSONの応答には、XMLの応答には含まれる、エンティティのルート名は含まれません。次のXML応答のemployeeルート/グループ名を参照してください。ルート名は、それを示すエンティティ名に由来します。

JSON

{
"firstName":"John",
"lastName": "Smith",
…
}

XML

<?xml version="1.0" encoding="UTF-8"?>
<employee>
<firstName>John</firstName>
<lastName>Smith</lastName>
…
</employee>

20.2.7.1 基本データ型

RESTfulデータ・サービスの応答では、基本データ型およびプリミティブは単純なJSONまたはXMLフィールドとして示されます。次に例を示します。

JSON

{
"firstName":"John",
"lastName": "Smith",
…
}

XML

<?xml version="1.0" encoding="UTF-8"?>
<employee>
<firstName>John</firstName>
<lastName>Smith</lastName>
…
</employee>

20.2.7.2 リンクおよびリレーションシップ

RESTfulデータ・サービスの処理では、JPAへの組込みおよび要素コレクションを除き、すべてのリレーションシップは参照で返されます。

relationshipsとは、1対1および1対多などエンティティの(JPA)リレーションシップをポイントするリンクです。たとえば、従業員が複数の電話番号(1対多)を保有しているとします。従業員が読み取られると、応答には従業員と電話エンティティ間のリレーションシップをポイントするリレーションシップ・リンクに加え、リンクの一覧を含むようになり、各リンクは従業員が所有する(一意の)電話番号をポイントします。次に例を示します。

{
"firstName": "Jacob",
"gender": "Male",
"id": 743627,
"lastName": "Smith",
"version": 1,
"_relationships": [
{
"_link": {
"href": "http://localhost:8080/eclipselink.jpars.test/persistence/hr/entity/Employee/743627/phoneNumbers",
"rel": "phoneNumbers"
}
}
],

"phoneNumbers": [
{
"_link": {
"href": "http://localhost:8080/eclipselink.jpars.test/persistence/hr/entity/PhoneNumber/743627+cell",
"method": "GET",
"rel": "self"
}
},
{
"_link": {
"href": "http://localhost:8080/eclipselink.jpars.test/persistence/hr/entity/PhoneNumber/743627+work",
"method": "GET",
"rel": "self"
}
}
]
}

組込みオブジェクトおよび要素のコレクションは完全に私有の(依存)オブジェクトです。IDは持たず、ElementCollectionにはカスケード・オプションはありません。ターゲット・オブジェクトは常に、その親と永続化、マージおよび削除されます。したがって、RESTfulデータ・サービスでは、リンクを提供するのではなく、これらのオブジェクトの応答を直接組込みます。たとえば、EmployeeオブジェクトでEmploymentPeriodがEmbeddedと定義されているとします。Employeeが読み取られると、応答にはEmploymentPeriodに対するリンクではなく、それを組込みオブジェクトとして含むようになります。リレーションシップは現在、組込み属性としてはサポートされていません。次の例を参照してください。

{
"firstName": "John",
"lastName": "Smith",

"employmentPeriod": {
"startDate": "2010-04-23T14:12:03.905-04:00",
"endDate": "2013-01-23T12:00:02.301-04:00",
"_relationships": []
},
...
}

同様に、要素のコレクションも、RESTfulデータ・サービスの応答にリンクとしてではなく直接含まれます。たとえば、EmployeeオブジェクトでCertificationオブジェクトのコレクションとして"certifications"属性が定義されているとします。Employeeが読み取られると、応答にはリンクではなくCertificationオブジェクトのリストが含まれます。

{
"firstName": "John",
"lastName": "Smith",
"certifications": [
{
"issueDate": "2013-04-23T15:02:23.071-04:00",
"name": "Java"
},
{
"issueDate": "2010-05-23T11:02:23.033-04:00",
"name": "Weblogic"
}
],
...
}

20.3 その他の参考資料

この章のソリューションが実装されているその他のテクノロジおよびツールの詳細は、次の参考資料を参照してください。

- http://docs.oracle.com/javaee/6/tutorial/doc/giepu.htmlのJava EE 6チュートリアルのJAX-RSでのRESTful Webサービスの構築に関する項。

- http://wiki.eclipse.org/EclipseLink/Examples/REST/GettingStartedのRESTfulサービスの例に関する項。

- http://jcp.org/en/jsr/detail?id=311の「JSR 311: JAX-RS: The Java API for RESTful Web Services」。

- http://jersey.java.net/のJerseyプロジェクト。

20.4 RESTfulデータ・サービスのAPIリファレンス

次の種類のRESTful処理は、RESTfulデータ・サービスを使用する際に、HTTPを使用してJPAで使用できます。

- エンティティ操作

- リレーションシップに対するエンティティ操作

- 問合せ操作

- 基本操作

- メタデータ操作

エンティティ操作

エンティティ操作とは、永続性ユニット内の特定の種類のエンティティに対して実行する操作です。

エンティティ操作の基本URIは次のとおりです。

/persistence/{version}/{unit-name}/entity/{type}/*

{type}値は、タイプ名(ディスクリプタ・エイリアス)を意味します。

サポートされるエンティティ操作は次のとおりです。

- FIND

- PERSIST

- MERGE

- DELETE

FIND

HTTPリクエストの構文

GET /persistence/{version}/{unit-name}/entity/{type}/{id}?{hints}

ここで、

- {id}は文字列です。

- hintsは、キーがEclipseLink問合せのヒント名であるHTTP問合せパラメータを使用して指定します。

使用例

GET http://localhost:8080/exampleApp/persistence/v1.0/ExamplePU/entity/Foo/1

次のものを生成

JSONまたはXML

応答

- OKとエンティティを含むペイロード

- エンティティが存在しない場合はNOT_FOUND

使用状況

コンポジット・キー

コンポジット・キーがサポートされています。+は予約文字で、キーを示すフィールドには使用できません。コンポジット・キーは、+文字を使用して分割され、Javaの属性名のデフォルトのソート順に従って指定される必要があります。

たとえば、Phoneエンティティに、extB=123およびextA=321という属性があるとします。このエンティティを探すURLは、次のとおりです。

http://localhost:8080/exampleApp/persistence/v1.0/ExamplePU/entity/Phone/321+123

Javaでソートされる場合、extAはextBの前になるので、321は123の前になります。

結果のキャッシュ

デフォルトのEclipseLinkおよびHTTPのキャッシュが有効になっており、標準の方法で構成されています。

リフレッシュ

Refreshの問合せのヒントにfindを使用してEntityManager.refresh操作を起動できます。

属性

エンティティの属性にナビゲート(たとえば、単一のRESTリクエストで従業員と関連付られているAddressエンティティを取得)する場合、次のように1レベルまでサポートされています。

/persistence/v1.0/{unit-name}/entity/{type}/{id}/{relationship}は機能します。

これに対し、

/persistence/v1.0/{unit-name}/entity/{type}/{id}/{relationship}/{index}/{relationship2}は機能しません。

PERSIST

HTTPリクエストの構文

PUT /persistence/{version}/{unit-name}/entity/{type}

使用例

PUT http://localhost:8080/exampleApp/persistence/v1.0/ExamplePU/entity/Foo

次のものを使用

JSONまたはXML

ペイロード

エンティティ

次のものを生成

JSONまたはXML

応答

永続性操作によって返されたエンティティを含むペイロード

使用状況

多重呼出し不変であるにはPUTが必要です。その結果、サーバーがIDフィールドの提供を期待するオブジェクトで呼び出されると失敗します。これは一般的に、メタデータが生成されたキーを指定し、そのキーを含むフィールドに値がない場合に発生します。

MERGE

HTTPリクエストの構文

POST /persistence/{version}/{unit-name}/entity/{type}

使用例

POST http://localhost:8080/exampleApp/persistence/v1.0/ExamplePU/entity/Foo

次のものを使用

JSONまたはXML

ペイロード

エンティティ

次のものを生成

JSONまたはXML

応答

マージ操作によって返されたエンティティを含むペイロード

マージはオブジェクト・グラフを取り、比較を介して永続性コンテキストの一部とします。これは、オブジェクトと関係するすべてのオブジェクトをすでに存在するものと比較し、INSERT、UPDATE、DELETEを発行して、そのオブジェクトを永続性コンテキストに配置します。

DELETE

HTTPリクエストの構文

DELETE /persistence/{version}/{unit-name}/entity/{type}{id}

ここで{id}は、文字列を使用して定義します。

使用例

DELETE http://localhost:8080/exampleApp/persistence/v1.0/ExamplePU/entity/Foo/1

応答

OK

リレーションシップに対するエンティティ操作

リレーションシップ操作の基本URIは次のとおりです。

/persistence/{version}/{unit-name}/entity/{entity}/{id}/{relationship}

サポートされるリレーションシップ操作は次のとおりです。

- READ

- ADD

- REMOVE

READ

この操作を使用すると、リレーションシップの値を取得できます。

HTTPリクエストの構文

GET /persistence/{version}/{unit-name}/entity/{type}/{id}/{relationship}

ここで、

- {id}は文字列です。

- {relationship}はリレーションシップのJPA名です。

使用例

GET http://localhost:8080/exampleApp/persistence/v1.0/ExamplePU/entity/Foo/1/myRelationship

次のものを生成

JSONまたはXML

応答

- OK、エンティティまたはエンティティのリストを含むペイロード

- エンティティが存在しない場合はNOT_FOUND

ADD

この操作を使用すると、多対1のリレーションシップのリストを追加したり、値を置換できます。

HTTPリクエストの構文

POST /persistence/{version}/{unit-name}/entity/{type}/{id}/{relationship}?{partner}

注意:

partnerは問合せのパラメータとして指定する必要があります。partnerはマトリックス・パラメータとしては指定しないでください。

例

一方向のリレーションシップの場合、次のように{partner}は不要です。

POST http://localhost:8080/exampleApp/persistence/v1.0/ExamplePU/entity/Foo/1/myRelationship

双方向のリレーションシップの場合、リレーションシップの逆側を構成する属性名を入力する必要があります。たとえば、リレーションシップの逆側がBid.auctionであるとき、Auction.bidを更新する場合、次を使用します。

POST http://localhost:8080/exampleApp/persistence/v1.0/ExamplePU/entity/Foo/1/myRelationship?partner=bid

次のものを使用

JSONまたはXML

ペイロード

新しい値のエンティティ。

注意:

リレーションシップ・オブジェクトは値または参照として渡すことができます。「値渡し対参照渡し」を参照してください。

次のものを生成

JSONまたはXML

応答

要素が追加されたエンティティを含むペイロード

REMOVE

リストから特定のエンティティを削除したり、多対1のリレーションシップでnullを削除するにはこの操作を使用します。

HTTPリクエストの構文

DELETE /persistence/{version}/{unit-name}/entity/{type}/{id}/{relationship}?{relationshipListItemId}

ここで、relationshipListItemIdはオプションの問合せパラメータです。relationshipListItemIdは、リストから削除する{relationship}がリストの場合のみ意味があります。relationshipListItemIdは、リレーションシップ・リストのそのメンバーのみを削除する必要がある場合、リレーションシップ・リストのメンバーのidに設定します。relationshipListItemIdを指定しない場合は、{relationship}で指定されたリスト全体が削除されます。

使用例

DELETE http://localhost:8080/exampleApp/persistence/v1.0/ExamplePU/entity/Foo/1/myRelationship

次のものを使用

JSONまたはXML

注意:

リレーションシップ・オブジェクトは値または参照として渡すことができます。「値渡し対参照渡し」を参照してください。

次のものを生成

JSONまたはXML

応答

- OK

- 要素が削除されたエンティティを含むペイロード

問合せ操作

問合せ操作の基本URIは次のとおりです。

GET /persistence/{version}/{unit-name}/query/{name}{params}

次の問合せ操作がサポートされています。

JPAでは、読取りを実行する名前付きの問合せは2とおりの方法で実行できます。いずれもREST APIでサポートされています。これらは次のとおりです。

- 結果を返す問合せ一覧

- 更新/削除の問合せ

結果を返す問合せ一覧

HTTPリクエストの構文

GET /persistence/{version}/{unit-name}/query/{name};{parameters}? {hints}

ここで、

- parametersは、HTTPマトリックス・パラメータを使用して指定します。

- hintsは、HTTPの問合せパラメータおよびEclipseLinkの問合せのヒント名であるキーを使用して指定します。

例

GET http://localhost:8080/exampleApp/persistence/v1.0/ExamplePU/query/Foo.findByName;name=myname

GET http://localhost:8080/exampleApp/persistence/v1.0/ExamplePU/query/Foo.findByName;name=myname?eclipselink.jdbc.max-results=500

次のものを生成

JSONまたはXML

応答

エンティティのリストを含むペイロード。XML応答には、アイテムのコレクションのグループ名としてListが含まれ、また返されたコレクションの各メンバーのグループ名としてitemが含まれます。JSONでは、角括弧[]を使用しコレクションをカプセル化し、波括弧{}を使用し、コレクションの各メンバーをカプセル化します。次に例を示します。

XMLの例

<?xml version="1.0" encoding="UTF-8"?>
<List>
<item>
<firstName>Miles</firstName>
<lastName>Davis</lastName>
<manager>
<firstName>Charlie</firstName>
<lastName>Parker</lastName>
<gender>Male</gender>
<id>26</id>
</manager>
</item>
<item>
<firstName>Charlie</firstName>
<lastName>Parker</lastName>
<manager>
<firstName>Louis</firstName>
<lastName>Armstrong</lastName>
<gender>Male</gender>
<id>27</id>
</manager>
</item>
</List>

JSONの例

[
{
"firstName": "Miles",
"lastName": "Davis",
"manager": {
"firstName": "Charlie",
"lastName": "Parker",
"gender": "Male",
"id": 26
}
},
{
"firstName": "Charlie",
"lastName": "Parker",
"manager": {
"firstName": "Louis",
"lastName": "Armstrong",
"gender": "Male",
"id": 27
}
}
]

更新/削除の問合せ

HTTPリクエストの構文

POST /persistence/{version}/{unit-name}/query/{name};parameters?hints

ここで、

- parametersは、HTTPマトリックス・パラメータを使用して指定します。

- hintsは、HTTPの問合せパラメータおよびEclipseLinkの問合せのヒント名であるキーを使用して指定します。

例

POST http://localhost:8080/exampleApp/persistence/v1.0/ExamplePU/query/Foo.deleteAllByName;name=myname

POST http://localhost:8080/exampleApp/persistence/v1.0/ExamplePU/query/Foo.updateName;name=myname?eclipselink.jdbc.max-results=500

次のものを生成

JSONまたはXML

応答

更新または削除するエンティティの数を含むペイロード

単一リクエスト問合せ

HTTPリクエストの構文

GET /persistence/{version}/{unit-name}/singleResultQuery/{name};{parameters}?{hints}

ここで、

- parametersは、HTTPマトリックス・パラメータを使用して指定します。

- hintsは、HTTPの問合せパラメータおよびEclipseLinkの問合せのヒント名であるキーを使用して指定します。

使用例

GET http://localhost:8080/exampleApp/persistence/v1.0/ExamplePU/singleResultQuery/Foo.findByName;name=myname

次のものを生成

JSON、XMLまたはapplication/octet-stream

応答

エンティティを含むペイロード

基本操作

次に基本操作を示します。

- 既存の永続性ユニットの列挙

既存の永続性ユニットの列挙

HTTPリクエストの構文

GET /persistence/{version}

使用例

GET http://localhost:8080/exampleApp/persistence/v1.0

次のものを生成

JSONまたはXML

応答

永続性ユニット名一覧およびそのメタデータへのリンクを含むペイロード。次に例を示します。

[
{

"_link": {
"href": "http://localhost:8080/exampleApp/persistence/v1.0/employee/metadata",
"method": "application/json",
"rel": "employee"
}
},
{
"_link": {
"href": "http://localhost:8080/exampleApp/persistence/v1.0/traveler/metadata",
"method": "application/json",
"rel": "traveler"
}
}
]

メタデータ操作

次のメタデータ操作がサポートされています。

- 永続性ユニットのタイプの列挙

- 永続性ユニットの問合せの列挙

- 特定のエンティティの説明

永続性ユニットのタイプの列挙

HTTPリクエストの構文

GET /persistence/{version}/{unit-name}/metadata

使用例

GET http://localhost:8080/exampleApp/persistence/v1.0/ExamplePU/metadata

次のものを生成

JSON

応答

- OKと次のように、より詳細なメタデータへのリンクを含むタイプ一覧を含むペイロード

{
"persistenceUnitName": "hr",
"types": [
{
"_link": {
"href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/metadata/entity/Employee",
"method": "application/json",
"rel": "Employee"
}
},
{
"_link": {
"href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/metadata/entity/PhoneNumber",
"method": "application/json",
"rel": "PhoneNumber"
}
}
]
}

- 永続性ユニットが見つからない場合はNOT_FOUND

永続性ユニットの問合せの列挙

HTTPリクエストの構文

GET /persistence/{version}/{unit-name}/metadata/query

使用例

GET http://localhost:8080/exampleApp/persistence/v1.0/ExamplePU/metadata/query

次のものを生成

JSON

応答

- OKと次のように、利用可能な問合せをすべて含むリストのペイロード

[
{
"queryName": "Employee.count",
"returnTypes": [
"Long"
],
"linkTemplate": {
"method": "get",
"href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/Employee.count",
"rel": "execute"
},
"jpql": "SELECT count(e) FROM Employee e"
},
{
"queryName": "EmployeeAddress.getRegion",
"returnTypes": [
"String",
"String",
"String"
],
"linkTemplate": {
"method": "get",
"href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/EmployeeAddress.getRegion",
"rel": "execute"
},
"jpql": "SELECT u.postalCode, u.province, u.street FROM EmployeeAddress u"
},
{
"queryName": "Employee.getPhoneNumbers",
"returnTypes": [
"String",
"String",
"PhoneNumber"
],
"linkTemplate": {
"method": "get",
"href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/Employee.getPhoneNumbers",
"rel": "execute"
},
"jpql": "SELECT e.firstName, e.lastName, pn FROM Employee e JOIN e.phoneNumbers pn"
},
{
"queryName": "EmployeeAddress.getPicture",
"returnTypes": [
"byte[]"
],
"linkTemplate": {
"method": "get",
"href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/EmployeeAddress.getPicture;id={id}",
"rel": "execute"
},
"jpql": "SELECT u.areaPicture FROM EmployeeAddress u where u.id = :id"
},
{
"queryName": "EmployeeAddress.updatePostalCode",
"returnTypes": [
"EmployeeAddress"
],
"linkTemplate": {
"method": "post",
"href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/EmployeeAddress.updatePostalCode;postalCode={postalCode};id={id}",
"rel": "execute"
},
"jpql": "UPDATE EmployeeAddress u SET u.postalCode = :postalCode where u.id = :id"
},
{
"queryName": "Employee.salaryMax",
"returnTypes": [
"int",
"Object"
],
"linkTemplate": {
"method": "get",
"href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/Employee.salaryMax",
"rel": "execute"
},
"jpql": "SELECT e.id, max(e.salary) AS max_salary from Employee e GROUP BY e.id, e.salary"
},
{
"queryName": "EmployeeAddress.getAll",
"returnTypes": [
"EmployeeAddress"
],
"linkTemplate": {
"method": "get",
"href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/EmployeeAddress.getAll",
"rel": "execute"
},
"jpql": "SELECT u FROM EmployeeAddress u"
},
{
"queryName": "EmployeeAddress.getById",
"returnTypes": [
"EmployeeAddress"
],
"linkTemplate": {
"method": "get",
"href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/EmployeeAddress.getById;id={id}",
"rel": "execute"
},
"jpql": "SELECT u FROM EmployeeAddress u where u.id = :id"
},
{
"queryName": "Employee.getManagerById",
"returnTypes": [
"String",
"String",
"Employee"
],
"linkTemplate": {
"method": "get",
"href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/Employee.getManagerById;id={id}",
"rel": "execute"
},
"jpql": "select u.firstName, u.lastName, u.manager from Employee u where u.id = :id"
},
{
"queryName": "Employee.findAll",
"returnTypes": [
"Employee"
],
"linkTemplate": {
"method": "get",
"href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/Employee.findAll",
"rel": "execute"
},
"jpql": "SELECT e FROM Employee e ORDER BY e.id"
},
{
"queryName": "Employee.getManager",
"returnTypes": [
"String",
"String",
"Employee"
],
"linkTemplate": {
"method": "get",
"href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/Employee.getManager",
"rel": "execute"
},
"jpql": "select u.firstName, u.lastName, u.manager from Employee u"
}
]

- 永続性ユニットが見つからない場合はNOT_FOUND

特定のエンティティの説明

HTTPリクエストの構文

GET /persistence/{version}/{unit-name}/metadata/entity/ type

使用例

GET http://localhost:8080/CustomerApp/persistence/v1.0/Inventory/metadata/entity/Customer

次のものを生成

JSON

応答

- OKと次のように、エンティティの詳細およびそれに対して実行可能な操作を含むペイロード

{
"name": "Employee",
"attributes": [
{
"name": "id",
"type": "int"
},
{
"name": "firstName",
"type": "String"
},
{
"name": "gender",
"type": "Gender"
},
{
"name": "lastName",
"type": "String"
},
{
"name": "salary",
"type": "double"
},
{
"name": "version",
"type": "Long"
},
{
"name": "period",
"type": "EmploymentPeriod"
},
{
"name": "manager",
"type": "Employee"
},
{
"name": "office",
"type": "Office"
},
{
"name": "address",
"type": "EmployeeAddress"
},
{
"name": "certifications",
"type": "List<Certification>"
},
{
"name": "responsibilities",
"type": "List<String>"
},
{
"name": "projects",
"type": "List<Project>"
},
{
"name": "expertiseAreas",
"type": "List<Expertise>"
},
{
"name": "managedEmployees",
"type": "List<Employee>"
},
{
"name": "phoneNumbers",
"type": "List<PhoneNumber>"
}
],
"linkTemplates": [
{
"method": "get",
"href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/entity/Employee/{primaryKey}",
"rel": "find"
},
{
"method": "put",
"href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/entity/Employee",
"rel": "persist"
},
{
"method": "post",
"href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/entity/Employee",
"rel": "update"
},
{
"method": "delete",
"href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/entity/Employee/{primaryKey}",
"rel": "delete"
}
],
"queries": [
{
"queryName": "Employee.count",
"returnTypes": [
"Long"
],
"linkTemplate": {
"method": "get",
"href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/Employee.count",
"rel": "execute"
},
"jpql": "SELECT count(e) FROM Employee e"
},
{
"queryName": "Employee.getPhoneNumbers",
"returnTypes": [
"String",
"String",
"PhoneNumber"
],
"linkTemplate": {
"method": "get",
"href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/Employee.getPhoneNumbers",
"rel": "execute"
},
"jpql": "SELECT e.firstName, e.lastName, pn FROM Employee e JOIN e.phoneNumbers pn"
},
{
"queryName": "Employee.salaryMax",
"returnTypes": [
"int",
"Object"
],
"linkTemplate": {
"method": "get",
"href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/Employee.salaryMax",
"rel": "execute"
},
"jpql": "SELECT e.id, max(e.salary) AS max_salary from Employee e GROUP BY e.id, e.salary"
},
{
"queryName": "Employee.getManagerById",
"returnTypes": [
"String",
"String",
"Employee"
],
"linkTemplate": {
"method": "get",
"href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/Employee.getManagerById;id={id}",
"rel": "execute"
},
"jpql": "select u.firstName, u.lastName, u.manager from Employee u where u.id = :id"
},
{
"queryName": "Employee.findAll",
"returnTypes": [
"Employee"
],
"linkTemplate": {
"method": "get",
"href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/Employee.findAll",
"rel": "execute"
},
"jpql": "SELECT e FROM Employee e ORDER BY e.id"
},
{
"queryName": "Employee.getManager",
"returnTypes": [
"String",
"String",
"Employee"
],
"linkTemplate": {
"method": "get",
"href": "http://localhost:8080/eclipselink.jpars.test/persistence/v1.0/hr/query/Employee.getManager",
"rel": "execute"
},
"jpql": "select u.firstName, u.lastName, u.manager from Employee u"
}
]
}

- 永続性ユニットが見つからない場合はNOT_FOUND

21 TopLinkライブ・データ問合せを使用したデータの更新

この章では、TopLinkのライブ・データ問合せ(ライブ問合せ)を使用して、バッキング・データ・ストアで変更を監視し、その後クライアント・アプリケーションに非同期的に変更されたすべてのデータを送信する方法を説明します。

- 21.1項「ソリューションの概要」

- 21.2項「ソリューションの実装」

- 21.3項「その他の参考資料」

ユース・ケース

TopLinkが有効なアプリケーションで問合せを実行すると、バッキング・データ・ストアのデータを追加、変更または削除できます。問合せを再実行せずに、更新に関する情報がアプリケーションで受信されることが重要です。

解決方法

TopLinkのライブ問合せをOracle Database連続問合せ通知(CQN)とともに使用して、データの変更をクライアントに通知するためにマージ・トラッキングをキャッシュします。

コンポーネント

- Oracle 11gR2 (11.2) (以上の)データベース

- TopLink 12cリリース1 (12.1.2)以上。

注意:

TopLinkのコア機能は、Eclipse Foundationのオープン・ソースの永続性フレームワークであるEclipseLinkが提供していますが、TopLinkのライブ・データはOracle TopLinkでのみ利用できます。

例

Oracle WebLogic Server WebソケットでTopLinkライブ問合せを使用する例については、http://www.oracle.com/toplink/でtlds.live.wsの例を参照してください。

21.1 ソリューションの概要

TopLinkのライブ問合せをOracle Database連続問合せ通知(CQN)とともに使用すると、バッキング・データ・ストアの変更をクライアント・アプリケーションに非同期的に通知するためにTopLinkでマージ・トラッキングをキャッシュできます。データベース(およびオプションでキャッシュ)では、問合せの基準と一致するデータ変更が監視され、それらの変更はクライアントに返されます。

21.1.1 Oracle Database CQNの概要およびTopLinkのキャッシュのトラッキング

CQNは、アプリケーションが変更通知をデータベースに対して登録することを許可するOracle Databaseの機能です。問合せを登録すると、問合せの結果がトランザクションによって変更されると、アプリケーションにデータベースから通知されるようにできます。この種類のCQN通知は、問合せ結果変更通知(QRCN)といいます。

注意:

11g以前のOracle Databaseリリースでは、変更通知機能はデータベース変更通知(DCN)と呼ばれていました。リリース11gでは、Oracle Database連続問合せ通知(CQN)に名前が変更されています。

TopLinkライブ問合せではQRCNを利用し、問合せに指定した基準と一致するデータに対する変更が、クライアント通知の実装を介してアプリケーションに返されるようになっています。

注意:

最初の問合せの実行と変更結果へのサブスクライブは、2つの操作で行う必要があります。

CQNおよびQRCNの詳細は、『Oracle Database開発者ガイド』の連続問合せ通知(CQN)の使用に関する項を参照してください。特に、問合せ結果変更通知(QRCN)に関する項を参照してください。

キャッシュに対するサブスクリプションはoracle.toplink.dataservices.livedata.cache.CacheSubscriptionProviderクラスを介して提供されます。

21.1.2 TopLinkライブ・データ問合せの作成および使用

問合せに名前を付け、データベース(オプションでキャッシュ)のイベントに基づいて通知をサブスクライブし、プロパティ・オブジェクトを介してサブスクリプションを構成します。

ライブ・データ問合せを設定する主な手順は次のとおりです。

- ClientNotifierインタフェースの実装を定義する。

- QRCNサブスクリプションを構成するプロパティ・オブジェクトを作成する。

- QRCN通知をサブスクライブする。

- 使用する名前付き問合せの名前を指定する。QRCNによってサポートされている問合せの種類のガイドラインについては、『Oracle Database開発者ガイド』の連続問合せ通知(CQN)の使用に関する項を参照してください。

- 問合せのパラメータを指定します。

- サブスクリプションを作成します。

- サブスクリプションにClientNotifierの実装を追加します。

- ClientNotifierの実装を作成および追加します。

通知をサブスクライブするには、データベースのイベントに基づくのみでなく、キャッシュ内のイベントに基づいて通知をサブスクライブすることも可能です。キャッシュ・サブスクリプションは、データベース・サブスクリプションで使用しているのと同じ、問合せ、パラメータおよびClientNotifierを使用して作成します。

21.2 ソリューションの実装

この項では、データ変更をクライアントに通知するTopLinkライブ問合せを設定および使用する次のタスクについて説明します。

- 手順1: 前提条件

- 手順2: データベースの権限の付与

- 手順3: ライブ・データ問合せおよびCQNサブスクリプションの作成

21.2.1 手順1: 前提条件

ライブ問合せを使用するには、次が必要です。

- Oracle Database 11.2.0.2以上

- TopLink 12cリリース1 (12.1.2)以上。

21.2.2 手順2: データベース権限の付与

他の許可に加え、データベース・ユーザーには、CHANGE NOTIFICATION権限が付与されている必要があります。これを実行するには、SYSなどのDBA権限を持っているか、データベース管理者にそれを適用してもらう必要があります。

grant change notification to user

Oracle Databaseの権限の付与の詳細は『Oracle Databaseセキュリティ・ガイド』の権限とロール認可の構成に関する項を参照してください。

21.2.3 手順3: ライブ・データ問合せおよびCQNサブスクリプションの作成

例21-1の例に従って、ライブ・データ問合せおよびCQNサブスクリプションを作成します。この例では、特定のPersistenceContextでCQN通知のサブスクリプションを定義するクラス定義の部分を示します。

注意:

完全なクラス定義には、クライアントに通知するコード(およびオプションでロギング)も含まれます。これについては、この章では説明しません。

例21-1 TopLinkライブ・データ問合せのCQN通知へのサブスクリプション

...
// Import TopLink Live Data classes
import oracle.toplink.dataservices.DataServicePersistenceContext;
import oracle.toplink.dataservices.livedata.Subscription;
import oracle.toplink.dataservices.livedata.SubscriptionFactory;
import oracle.toplink.dataservices.livedata.cache.CacheSubscriptionProvider;
import oracle.toplink.dataservices.livedata.notification.ClientNotifier;
import oracle.toplink.dataservices.livedata.notification.Notification;
import oracle.toplink.dataservices.livedata.notification.NotificationType;
import oracle.toplink.dataservices.livedata.qcn.QCNSubscriptionProvider;
import weblogic.websocket.WebSocketConnection;
...
// Client notifier code---
class Notifier implements ClientNotifier {
// The implementation of the client notifier)
...
}

// Notification subscription code---

// The name of the query.
private String queryName;

// The parameters associated with the query.
private Map<String, String> parameters;

// The persistence context that this CQN notifier listens to.
private DataServicePersistenceContext persistenceContext;

// Returns the query parameters associated with this notifer.
Map<String, String> getParameters() {
return this.parameters;
}

// Returns the name of the query that this notifier listens to.
String getQueryName() {
return this.queryName;
}

// Subscribe with the associated PersistenceContext, to listen to query result change events.
public void subscribe() {

// properties object for configuation of the subscription
Map<String, Object> properties = new HashMap<String, Object>();

// subscribe to notifcation through Oracle CQN
properties.put(SubscriptionFactory.SUBSCRIPTION_TYPE, QCNSubscriptionProvider.QCN);
properties.put(CacheSubscriptionProvider.QUERY_PARAMETERS, this.parameters);
properties.put(CacheSubscriptionProvider.QUERY_NAME, this.queryName);
Subscription subscription = this.persistenceContext.getSubscriptionFactory().
getOrCreateSubscription(this.queryName, properties);
// Register for QRCN subscription
subscription.addClientNotifier(this);

properties.put(SubscriptionFactory.SUBSCRIPTION_TYPE, CacheSubscriptionProvider.CACHE);
subscription = this.persistenceContext.getSubscriptionFactory().
getOrCreateSubscription(this.queryName, properties);
// Register for cache subscription
subscription.addClientNotifier(this);
}

public String toString() {
return "Notifier [query = " + this.queryName + "]";
}

// Unsubscribe from the PersistenceContext listening to query result change events.
*/
public void unsubscribe() {
Map<String, Object> properties = new HashMap<String, Object>();
properties.put(SubscriptionFactory.SUBSCRIPTION_TYPE, QCNSubscriptionProvider.QCN);
properties.put(CacheSubscriptionProvider.QUERY_PARAMETERS, this.parameters);
properties.put(CacheSubscriptionProvider.QUERY_NAME, this.queryName);
Subscription subscription = this.persistenceContext.getSubscriptionFactory().getSubscription(this.queryName, this.parameters);
subscription.removeClientNotifier(this);
}
// Update the object with changes
public void updatedObject(Object updatedObject) {
sendMessage(updatedObject, NotificationType.UPDATE);
}

21.3 その他の参考資料

TopLinkライブ・データ問合せの詳細は、次を参照してください。

- Oracle Databaseで変更通知を使用する方法の詳細は、『Oracle Database開発者ガイド』の連続問合せ通知(CQN)の使用に関する項を参照してください。

22 キャッシュを無効にするためのデータベース・イベントの使用

この章では、JPAの共有データベースでキャッシュを使用することを可能にするOracle Database連続問合せ通知(CQN)に対するTopLinkのサポートについて説明します。

注意:

Oracle Database連続問合せ通知は、以前は、Oracle Database変更通知としても知られていました。

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

- 22.1項「ソリューションの概要」

- 22.2項「ソリューションの実装」

- 22.3項「ソリューションの制限」

- 22.4項「その他の参考資料」

ユース・ケース

ユーザーが、JPAアプリケーションで共有キャッシュを使用したいと考えていますが、外部アプリケーションによって同じデータベース・データが更新されてしまうか、キャッシュがクラスタ環境にあります。キャッシュには失効データが残ってしまう場合があります。

解決方法

Oracle Databaseには、データベースに対する変更をアプリケーションが登録できるAPIが用意されています。TopLinkでは、共有キャッシュで変更されたオブジェクトを無効にするために、Oracle Databaseへの登録とデータベースの変更イベントの処理をサポートしています。

コンポーネント

- Oracle 11gR2 (11.2) (以上の)データベース

- TopLink 12c (12.1.2)以上。

注意:

TopLinkのコア機能は、オープン・ソースのEclipse Foundationの永続性フレームワークであるEclipseLinkによって提供されています。EclipseLinkでは、Java Persistence API (JPA)、Java Architecture for XML Binding (JAXB)、および標準に基づいたその他の永続性テクノロジと、それらの標準の拡張が実装されます。TopLinkには、EclipseLinkのすべてに加え、Oracleの追加機能が含まれています。

- EclipseLinkライブラリ: eclipselink.jar。

- JDBCライブラリ: ojdbc6.jar。

- JPAライブラリ: persistence.jar。

例

JPAを使用するアプリケーションで連続問合せ通知および共有キャッシュの使用方法を示すサンプル・ファイルについては、EclipseLinkのドキュメントの「EclipseLink/Examples/JPA/DCN」を参照してください。

http://wiki.eclipse.org/EclipseLink/Examples/JPA/DCN

22.1 ソリューションの概要

EclipseLinkには、データベースのオブジェクトとリレーションシップに対するアクセスを減らす共有(L2)オブジェクト・キャッシュが用意されています。このキャッシュはデフォルトで有効で、他のアプリケーションまたはクラスタ環境において別のサーバーにある同じアプリケーションが、データベースの内容が直接変更しないかぎり通常は問題にはなりません。これによりキャッシュに無効なデータが生じる場合があります。

データベースの内容が変更された場合に、キャッシュの内容がデータベースと同期されることを保証するメカニズムが必要になります。このメカニズムは、EclipseLinkのOracle連続問合せ通知に対するサポートで提供されます。CQNによりJPA環境で共有キャッシュの使用が可能になります。

注意:

Oracle Database連続問合せ通知の機能の詳細は、『Oracle Database開発者ガイド』の連続問合せ通知(CQN)の使用に関する項を参照してください。『Oracle Database JDBC開発者ガイド』の連続問合せ通知に関する項も参照してください。

EclipseLinkでは、表の内容が変更されたときに、データベースからイベントを受け取る、Oracle Database連続問合せ通知への登録をサポートしています。変更の検出に、CQNはROWIDを使用し、プライマリ表の列レベルの変更を通知します。EclipseLinkでは、CQNが有効なクラスのすべての問合せにROWIDを含めます。EclipseLinkでは、Insert操作後にオブジェクトのROWIDも選択します。EclipseLinkでは、オブジェクトIdのみでなく、ROWIDのキャッシュ索引も維持します。EclipseLinkは、トランザクションを処理しているサーバーでキャッシュが無効にされないよう、トランザクションごとに1回データベースのトランザクションIDも選択します。

EclipseLinkは、OracleChangeNotificationListener (org.eclipse.persistence.platform.database.oracle.dcn.OracleChangeNotificationListener)リスナー・クラスを介して有効にされます。リスナーはOracle JDBCと統合して、データベースの変更イベントを受け取ることができます。リスナーを有効にするには、persistence.xmlファイルでeclipselink.cache.database-event-listenerプロパティの値としてOracleChangeNotificationListenerクラスへの完全なパスを指定します。

デフォルトでは、ドメインのすべてのエンティティに対して変更通知が登録されます。ただし、変更通知は、JavaファイルのCache注釈のdatabaseChangeNotificationType (org.eclipse.persistence.annotations.DatabaseChangeNotificationType)属性でタグ付けして、特定のクラスを選んで無効にすることもできます。この属性の値によって、エンティティが使用するデータベースに対する変更通知の種類が決定されます。databaseChangeNotificationType属性のデフォルト値はInvalidateです。クラスの変更通知を無効にするには、属性の値をNoneに設定します。

databaseChangeNotificationType属性は、永続性ユニットにデータベースの変更イベントを受け取るOracleChangeNotificationListenerクラスなどのデータベース・イベント・リスナーが構成されている場合のみ該当します。これによりデータベースに変更があったときに、EclipseLinkのキャッシュを無効にしたり、更新できます。

トランザクションでは、(失効データに対する書込みは失敗し、キャッシュが自動的に無効になる)オプティミスティック・ロックを使用することを強くお薦めします。エンティティに@Version注釈を含めると、プライマリ表のバージョン列には常に更新され、オブジェクトは常に無効化されます。

22.2 ソリューションの実装

この項では、JPA環境で共有キャッシュを有効にする次のタスクについて説明します。

- タスク1: データベースおよび表の設定

- タスク2: ユーザー権限の付与

- タスク3: クラスパスの設定

- タスク4: 変更通知に参加するクラスの識別

- タスク5: データベース・イベント・リスナーの追加

- タスク6: Javaファイルの編集

22.2.1 タスク1: データベースおよび表の設定

このソリューションでは、関心のある表がOracle 11gR2 (11.2)以上のデータベースに含まれ、それで作業していることが前提です。

22.2.2 タスク2: ユーザー権限の付与

他の許可に加え、データベース・ユーザーには、CHANGE NOTIFICATION権限が付与されている必要があります。これを実行するには、SYSなどのDBA権限を持っているか、データベース管理者にそれを適用してもらう必要があります。

grant change notification to user

次の例では、ユーザーSCOTTに変更通知権限を付与する例を示します。

...
define user="SCOTT"
define pass="tiger"
grant create session, alter session to &&user
/
grant resource, connect to &&user
/
grant select any dictionary to &&user
/
grant select any table to &&user
/
grant change notification to &&user
/
...

22.2.3 タスク3: クラスパスの設定

EclipseLinkライブラリのeclipselink.jar、JDBCライブラリのojdbc6.jar、JPAライブラリのpersistence.jarおよびドメイン・クラスがクラスパスにあることを確認します。

22.2.4 タスク4: 変更通知に参加するクラスの識別

デフォルトでは、ドメインのすべてのエンティティが変更通知に参加します。参加するエンティティを制限するには、いくつかの方法があります。たとえば、エンティティ・クラスをorm.xmlファイルの<entity class...>要素、persistence.xmlファイルの<exclude-unlisted-classes>要素、またはJARファイルに含めて示すことができます。

注意:

<exclude-unlisted-classes>要素は、Java SE環境で使用するようには意図されていません。

JavaファイルでCache注釈属性を使用して、エンティティ・クラスを除外することも可能です。詳細は、22.2.6.2項「変更通知からのクラスの除外(オプション)」を参照してください。

persistence.xmlファイルで<class>要素を使用して、エンティティ・クラスを指定することも可能です。次の例は、modelパッケージのOrder、OrderLineおよびCustomerクラスが変更通知に参加することを示します。完全なpersistence.xmlファイルの例は、例22-1を参照してください。

...
<class>model.Order</class>
<class>model.OrderLine</class>
<class>model.Customer</class>
...

22.2.5 タスク5: データベース・イベント・リスナーの追加

データベース・イベント・リスナーを指定するには、eclipselink.cache.database-event-listenerプロパティを使用します。連続問合せ通知のリスナーは、org.eclipse.persistence.platform.database.oracle.dcn.OracleChangeNotificationListenerクラスです。これによりデータベース・イベントによりEclipseLinkのキャッシュが無効になります。

次に、OracleChangeNotificationListenerクラスにeclipselink.cache.database-event-listenerプロパティを構成した例を示します。完全なpersistence.xmlファイルの例は、例22-1を参照してください。

...
<properties>
<property name="eclipselink.cache.database-event-listener" value="org.eclipse.persistence.platform.database.oracle.dcn.OracleChangeNotificationListener"/>
</properties>
...

次を使用することも可能です。

<property name="eclipselink.cache.database-event-listener" value="DCN">

persistence.xmlファイルの完全な例を例22-1に示します。変更通知に参加するクラスは、modelパッケージのOrder、OrderLineおよびCustomerクラスです。eclipselink.cache.database-event-listenerプロパティは、OracleChangeNotificationListenerクラスの完全パスに設定されます。

注意:

EclipseLinkがデフォルトのプロバイダであるコンテナで実行される場合、<provider>タグはオプションです。

例22-1 persistence.xmlのサンプル・ファイル

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence persistence_2_0.xsd"
version="2.0">
<persistence-unit name="acme" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>model.Order</class>
<class>model.OrderLine</class>
<class>model.Customer</class>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="eclipselink.cache.database-event-listener" value="DCN"/>
</properties>
</persistence-unit>
</persistence>

22.2.6 タスク6: Javaファイルの編集

通常、変更通知に参加する場合、データベース表に対応するJavaクラスは変更する必要がありません。ただし、@Version注釈でオプティミスティック・ロックを設定することが強く推奨されます。

永続性ユニットに列挙されるクラスを除外したい場合は、Javaファイルでタグ付けします。EclipseLinkはプライマリ表でのみ変更を追跡します。セカンダリ表も追跡されるよう変更するには、Javaファイルにそれを示します。

22.2.6.1 オプティミスティック・ロックの設定

失効データに対する書込みが失敗し、キャッシュを自動的に無効にするオプティミスティック・ロックを使用することを強くお薦めします。エンティティに@Version注釈を含めると、プライマリ表のバージョン列は常に更新されるので、古いバージョンのオブジェクトは常に無効化されます。

例22-2では、@Version注釈はCustomerエンティティに定義されています。versionの変数としてgetterおよびsetterが定義されていることに注意してください。

例22-2 @Version注釈の定義

...
@Entity
@Table(name="DBE_CUSTOMER")
public class Customer implements Serializable {
@Id
@GeneratedValue(generator="CUST_SEQ")
@TableGenerator(name="CUST_SEQ")
@Column(name="CUST_NUMBER")
private long id;

@Version
private long version;

...
public long getVersion() {
return version;
}

public void setVersion(long version) {
this.version = version;
}
...

22.2.6.2 変更通知からのクラスの除外(オプション)

Cache注釈のdatabaseChangeNotificationType属性を使用すると、変更通知を必要としないクラスを指定できます。変更通知からクラスを除外するには、次の例のとおり、属性をDatabaseChangeNotificationType.NONEに設定します。

...
@Entity
@Cache(databaseChangeNotificationType=DatabaseChangeNotificationType.NONE)
public class Order {
...

22.2.6.3 セカンダリ表での変更追跡(オプション)

EclipseLinkはプライマリ表でのみ変更を追跡します。セカンダリ表で更新が発生する場合、EclipseLinkはオブジェクトを無効にしません。セカンダリ表でも同様に追跡するには、エンティティに@Version注釈を追加します。

CQNでは、プライマリ表のイベントのみをリスニングします。セカンダリ表またはリレーションシップ表の変更は追跡しません。これは、Oracle CQNはROWIDのみ追跡し、プライマリ表、セカンダリ表およびリレーションシップ表のROWIDには相関関係がないためです。したがって、セカンダリ表またはリレーションシップ表が変更されたときにイベントを受け取るには、プライマリ表のバージョンを変更してイベントが返されるようにする必要があります。

22.3 ソリューションの制限

EclipseLinkの連続問合せ通知のサポートには、次の制限があります。

- プライマリ表で@Version注釈が使用され更新されないかぎり、セカンダリ表のオブジェクトが変更されてもその無効化はトリガーされません。

- プライマリ表で@Version注釈が使用され更新されないかぎり、オブジェクトのOneToMany、ManyToManyおよびElementCollectionのリレーションシップが変更されてもその無効化はトリガーされません。

22.4 その他の参考資料

この章のソリューションが実装されているその他のテクノロジおよびツールの詳細は、次の参考資料を参照してください。

- 『Oracle Database開発者ガイド』の連続問合せ通知(CQN)の使用に関する項

- 『Oracle Database JDBC開発者ガイド』の連続問合せ通知に関する項

- 「EclipseLink/Examples/JPA/DCN」: このページでは、DCNを採用しているJPA環境でのキャッシュ共有の例を説明しています。例を実行するサンプル・ファイルおよび手順が含まれています。EclipseLinkのドキュメントを参照してください。
http://wiki.eclipse.org/EclipseLink/Examples/JPA/DCN

23 NoSQLデータベースでTopLinkを使用する方法

この章では、インターネット・データベース、オブジェクト・データベース、XMLデータベース、レガシー・データベースなどのNoSQLデータベース・システムに、Oracle TopLinkを使用してオブジェクトをマップする機能を説明します。

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

- 23.1項「ソリューションの概要」

- 23.2項「ソリューションの実装」

- 23.3項「その他の参考資料」

ユース・ケース

TopLinkでNoSQLデータ・ソースをユーザーが使用する必要があります。

解決方法

TopLinkは、複数のNoSQLデータ・ソースをサポートしています。このソリューションでは、Oracle NoSQLおよびMongoDBの使用を説明しています。

コンポーネント

- TopLink 12cリリース1 (12.1.2)以上。

注意:

TopLinkのコア機能は、オープン・ソースのEclipse Foundationの永続性フレームワークであるEclipseLinkによって提供されています。EclipseLinkでは、Java Persistence API (JPA)、Java Architecture for XML Binding (JAXB)、および標準に基づいたその他の永続性テクノロジと、それらの標準の拡張が実装されます。TopLinkには、EclipseLinkのすべてに加え、Oracleの追加機能が含まれています。

- NoSQLデータ・ソース。

- JCAアダプタ。

例

関連情報については、次のEclipseLinkの例を参照してください。

- http://wiki.eclipse.org/EclipseLink/Examples/JPA/NoSQL

23.1 ソリューションの概要

EclipseLinkでは、JavaEE Connector Architectureを介して、NoSQLデータへのアクセスをサポートしています。(サード・パーティであるEclipseLinkが提供する、またはカスタム作成された)JCAを使用する必要があります。

NoSQLデータの多くは階層形式なので、一般に組込みオブジェクトが使用されています。一部のNoSQLアダプタでは、XMLデータをサポートしているので、NoSQLマップ済オブジェクトでは、XMLへのマッピング時にXMLマッピングを使用できます。

23.2 ソリューションの実装

この項では、JSONドキュメントから、またJSONドキュメントにオブジェクトを変換する際の次のタスクについて説明します。

- タスク1: データのマッピング

- タスク2: IDの定義

- タスク3: マッピングの定義

- タスク4: ロックの使用

- タスク5: 問合せの定義

- タスク6: データベースへの接続

23.2.1 タスク1: データのマッピング

NoSQLデータにマッピングを行うには、EclipseLinkの@NoSQL注釈およびXML要素の<no-sql>を使用して構成します。@NoSQL注釈では、クラスを非リレーショナル・データに対するマッピングとして定義します。@NoSQLは、JPAエンティティまたは組込み可能クラスと使用できます。

@NoSQL注釈では、データのdataTypeおよびdataFormatを指定できます。dataTypeは、使用しているNoSQLデータ・ソースにより異なります。

- MongoDBの場合、dataTypeは、JSONドキュメントのストア先のコレクション名です。

- Oracle NoSQLの場合、dataTypeは、主要なキー値の最初の部分になります。

dataFormatは、保存されるデータのタイプ構造(データ形式)によります。

- MongoDBでは、その構造化データベースにはMAPPEDを使用します。

- Oracle NoSQLでは、MAPPED (キー/値データ)またはXML (単一XML文書の場合)を使用します。

例23-1に、@Entityおよび@Embeddableクラスで@NoSQLを使用する方法を説明します。

例23-1 JSONでの@NoSql注釈の使用

@Entity
@NoSQL(dataType="orders", dataFormat=DataFormatType.MAPPED)
public class Order {
@Id
@GeneratedValue
@Field(name="_id")
private long id;
@Basic
@Field(name="description")
private String description;
@Embedded
@Field(name="deliveryAddress")
private Address deliveryAddress
@ElementCollection
@Field(name="orderLines")
private List<OrderLine> orderLines;
@ManyToOne
@JoinField(name="customerId")
private Customer customer;
}

@Embeddable
@NoSQL(dataFormat=DataFormatType.MAPPED)
public class OrderLine {
@Field(name="lineNumber")
private int lineNumber;
@Field(name="itemName")
private String itemName;
@Field(name="quantity")
private int quantity;
}

23.2.2 タスク2: IDの定義

EclipseLinkでは、非リレーショナル・データベースを使用する場合は、他のリレーショナル・エンティティ同様に、IDとして任意のフィールド(またはフィールドのセット)を使用できます。(アプリケーションに割り当てられた)自然IDを使用することも、(EclipseLinkによって割り当てられた)生成されたIDを使用することも可能です。

MongoDBでは、すべてのドキュメントに_idフィールドも必要です。_idフィールドがない場合、Mongoでは、UUID (Universally Unique Identifier)と類似したOID(オブジェクト識別子)を使用して_idフィールドを自動的に生成します。

- Mongo IDとして自然IDを使用する場合、他にリレーションシップをまったく指定せず、@Field (または@Column) 注釈を使用してフィールドを_idと命名します。
次に例を示します。

@Field(name="_id")
private long id;

- 生成されたMongo OIDをIDとして使用する場合、オブジェクトのIDフィールド・マッピングに単純に、@Id、@GeneratedValueおよび@Field(name="_id")注釈を含めます。
@GeneratedValueは、このID値の生成にMongo OIDを使用するようEclipseLinkに伝達します。Mongo OIDのかわりにUUIDを使用する場合は、@UUIDGenerator注釈を使用します。

注意:

MongoDBでは、@SequenceGeneratorまたは@TableGeneratorや、IDENTITY、TABLEおよびSEQUENCEの生成タイプはサポートしていません。

Mongo OIDまたはUUIDのIDは数値ではなく、Stringまたはbyte[]としてマップする必要があります。

次に例を示します。

@Id
@GeneratedValue
@Field(name="_id")
private String id;

23.2.3 タスク3: マッピングの定義

非リレーショナル・データベースの場合、EclipseLinkでは、オブジェクトをXMLやJSONなどの階層データにマップします。NoSQLでは、組込みデータや組込みコレクションを含むすべての既存のJPAマッピング注釈およびXMLをサポートしています。マッピング注釈(またはXML)を属性に定義しない場合、EclipseLinkではデフォルトのマッピングを使用します。

基本のマッピング

NoSQLのデフォルトはJPAのデフォルトであるため、最も単純なマッピングでも構成を行う必要はありません。Mongo BSONのドキュメントに使用されるフィールド名は、オブジェクト属性名(大文字)をミラーします。別のBSONフィールド名を使用するには、@Field注釈を使用します。

注意:

@Columnや@JoinColumnは使用しないでください。かわりに@Fieldと@JoinFieldを使用します。また、@JoinTableおよび@CollectionTable注釈はサポート対象外であるか不要です。

組込み値

組込み値を永続化するには、@Embedded注釈を使用し、組込みコレクションには@ElementCollection注釈を使用します。すべてのデータはXML文書に保存されるので、別途表(つまり、@CollectionTable)を用意する必要はありません。また、組込みオブジェクトはドキュメントにネストされ、一意のフィールド名を必要としないので、@AttributeOverride属性も不要です。

注意:

通常、正しくデフォルトが使用されるので、@Embedded注釈は使用する必要がありません。

ただし、EclipseLinkでは@ElementCollectionのマッピングにはデフォルトを使用しないので、この注釈を含める必要があります。

リレーションシップ

(@OneToOne、@ManyToOne、@OneToManyおよび@ManyToManyなどの)リレーションシップ注釈は、外部のリレーションシップでのみ使用します。ドキュメント内のリレーションシップでは、組込み値を使用する必要があります。

EclipseLinkの他のドキュメントに対する外部リレーションシップは、外部キーを使用し、完全にサポートされています。ターゲット・オブジェクトのIDは、ソース・オブジェクトのドキュメントにストアされます。コレクションには、IDのコレクションがストアされます。BSONドキュメントへの外部キー・フィールド名の定義には、@JoinField注釈が使用されます。

注意:

EclipseLinkでは、外部キーを両サイドに保存する必要があるため、非リレーショナル・データベースのリレーションシップに、mappedByオプションはサポートしていません。

また、問合せを使用しリレーションシップ・マッピングを定義することも可能です。ただし、注釈のかわりにDescriptorCustomizerを使用する必要があります。

例23-2 マッピングの例

@Basic
private String description;
@Basic
private double totalCost = 0;
@Embedded
private Address billingAddress;
@Embedded
private Address shippingAddress;
@ElementCollection
private List<OrderLine> orderLines = new ArrayList<OrderLine>();
@ManyToOne(fetch=FetchType.LAZY)
private Customer customer;

23.2.4 タスク4: ロックの使用

ロックに対するサポートは、NoSQLプラットフォームに依存しています。一部のNoSQLプラットフォームは、オプティミスティック・バージョン・ロックをサポートしています。

- Oracle NoSQL: ロックはサポート対象されていません。

- MongoDB: バージョン・ロックがサポートされています。

注意:

MongoDBではトランザクションはサポートされていません。トランザクション中にエラーが発生した場合、前に書き込まれたオブジェクトはロール・バックされません。

NoSQLプラットフォームがロックをサポートしない場合、@Version注釈(例23-3を参照)を使用し、merge()操作時にオブジェクトを有効にする必要があります。

例23-3 @Versionの使用

@Version
private long version;
...

23.2.5 タスク5: 問合せの定義

NoSQLで問合せを実行できるかどうかは、NoSQLプラットフォームに依存しています。一部のNoSQLデータ・ソースでは、それ独自の問合せ言語で動的な問合せがサポートされ、問合せが他ではまったくサポートされない場合があります。

23.2.5.1 JPQL問合せ

Java Persistence Query Language (JPQL)は、JPAで定義されている問合せ言語です。JPQLは、読取り(SELECT)、バルク更新(UPDATE)および削除(DELETE)に使用できます。JPQLは、(注釈やXMLを介して)NamedQueryで使用するか、EntityManager createQuery() APIを使用した動的問合せで使用します。

- Oracle NoSQL: find()、JPQLおよびCriteriaをIDまたはWHERE句なしでサポートしています。

- MongoDB: 結合、下位選択、グループ化および特定のデータベース関数のサポートは除く、いくつかの制限付きでJPQLおよびCriteriaの問合せをサポートしています。

例23-4 MongoDB JPQLの例

Query query = em.createQuery("Select o from Order o where o.totalCost > 1000");
List<Order> orders = query.getResultList();

Query query = em.createQuery("Select o from Order o where o.description like 'Pinball%'");
List<Order> orders = query.getResultList();

Query query = em.createQuery("Select o from Order o join o.orderLines l where l.description = :desc");
query.setParameter("desc", "shipping");
List<Order> orders = query.getResultList();

Query query = em.createQuery("Select o.totalCost from Order o");
List<BigDecimal> orders = query.getResultList();

23.2.5.2 ネイティブ問合せ

ネイティブSQL問合せは変換されず、データベースに直接渡されます。SQL問合せは、データベース固有の構文を必要とする高度な問合せに使用できます。

ネイティブSQL問合せは、NoSQLではサポートされていませんが、一部のNoSQLプラットフォームには独自のネイティブ問合せ言語があります。EclipseLinkは、その言語を使用したJPAネイティブ問合せをサポートしています。

- MongoDB: MongoDBネイティブ・コマンド言語を使用したJPAネイティブ問合せをサポートしています。

例23-5 MongoDBネイティブ問合せ

Query query = em.createNativeQuery("db.ORDER.findOne({\"_id\":\"" + oid + "\"})", Order.class);
Order order = (Order)query.getSingleResult();

23.2.6 タスク6: データベースへの接続

EclipseLinkは、persistence.xmlファイルを使用してNoSQLデータベースに接続します。特定のNoSQLプラットフォームを定義するには、<eclipselink.target-database>プロパティを使用します。また、接続は<eclipselink.nosql.connection-spec>プロパティで定義します。その他の接続値(db、portおよびhostも定義することができます。

注意:

Mongoデータベースのクラスタに接続するには、hostおよびportにカンマで区切り値を入力します。

例23-6 MongoDBのpersistence.xmlの例

<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence persistence_2_0.xsd" version="2.0">
<persistence-unit name="acme" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="eclipselink.target-database" value="org.eclipse.persistence.nosql.adapters.mongo.MongoPlatform"/>
<property name="eclipselink.nosql.connection-spec" value="org.eclipse.persistence.nosql.adapters.mongo.MongoConnectionSpec"/>
<property name="eclipselink.nosql.property.mongo.port" value="27017, 27017"/>
<property name="eclipselink.nosql.property.mongo.host" value="host1, host2"/>
<property name="eclipselink.nosql.property.mongo.db" value="acme"/>
</properties>
</persistence-unit>
</persistence>

23.3 その他の参考資料

この章のソリューションが実装されているその他のテクノロジおよびツールの詳細は、次の参考資料を参照してください。

- Oracle TopLinkによるJAXBアプリケーションの開発

- 『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』

- http://wiki.eclipse.org/EclipseLink/Development/Incubator/Platformの「EclipseLink Extensions Incubator」

24 Oracle DatabaseでOracle TopLinkを使用する方法

この章では、特にOracle Databaseプラットフォームをサポートするよう設計されたOracle TopLinkのEclipseLinkの機能を理解して使用する方法を説明します。

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

- 24.1項「ソリューションの概要」

- 24.2項「ソリューションの実装」

- 24.3項「その他の参考資料」

ユース・ケース

Oracle TopLinkには、すべてのデータベースに対応するよう設計された永続性ソリューションが用意されています。ただし、アプリケーションでOracle Databaseプラットフォームを使用する計画の場合は、Oracle Databaseに対する高度なサポートを利用できます。

解決方法

このソリューションは、TopLinkの様々なAPIやOracle製品によって実現されています。使用しているOracle Databaseの機能や製品に基づいて、アプリケーションで様々なOracle TopLinkのAPIの実装を選択します。

コンポーネント

- TopLink 12cリリース1 (12.1.2)以上。

注意:

TopLinkのコア機能は、オープン・ソースのEclipse Foundationの永続性フレームワークであるEclipseLinkによって提供されています。EclipseLinkでは、Java Persistence API (JPA)、Java Architecture for XML Binding (JAXB)、および標準に基づいたその他の永続性テクノロジと、それらの標準の拡張が実装されます。TopLinkには、EclipseLinkのすべてに加え、Oracleの追加機能が含まれています。

- Oracle Database

- アプリケーションで使用することが選択された機能に応じ、その他のOracle DatabaseおよびMiddleware製品が必要になります。

24.1 ソリューションの概要

EclipseLinkでは、Oracle Databaseプラットフォームを拡張サポートしています。Oracle Databaseを標準とするアプリケーションでは、このサポートにより使い勝手、パフォーマンス、拡張性およびセキュリティが向上します。EclipseLinkでは、Oracle JDBC固有のネイティブAPI、PL/SQL、Oracle Real Application Clusters (RAC)、Oracle仮想プライベート・データベース、Oracle Proxy AuthenticationおよびOracle Spatial and Graphをサポートしています。これらのテクノロジの詳細は、Oracle Databaseのドキュメントを参照してください。

Oracle Databaseプラットフォームに対するサポートの多くは、org.eclipse.persistence.platform.database.oracle*パッケージに含まれています。このAPIの詳細は、『Oracle TopLink Java APIリファレンス』を参照してください。

24.2 ソリューションの実装

この項では、テクノロジごとのソリューションをまとめています。このようにまとめることにより、開発者はソリューションの様々な部分を簡単に理解して、実装する部分を具体的に選択できます。

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

- Oracleプラットフォームに固有のAPIの使用

- EclipseLinkでのOracle PL/SQLの使用

- Oracle仮想プライベート・データベースの使用

- Oracle Proxy Authenticationの使用

- Oracle RACでのEclipseLinkの使用

- Oracle Spatial and Graphの使用

24.2.1 Oracleプラットフォームに固有のAPIの使用

Oracle Databaseプラットフォームに対するサポートは、org.eclipse.persistence.platform.database.OraclePlatformクラス、org.eclipse.persistence.platform.database.oracle*パッケージで提供され、Oracle XML Databaseに対するサポートはorg.eclipse.persistence.mappings.xdbパッケージで提供されています。このAPIの詳細は、『Oracle TopLink Java APIリファレンス』を参照してください。特定のOracle SQL型の詳細は、『Oracle Database JDBC Java APIリファレンス』を参照してください。

Oracle Databaseでは次がサポートされています。

- オプティミスティック・ロックを使用したバッチ書込み

- byte[]、Date、Time、TimestampおよびCalendarのネイティブSQL

- 大きな値に対してOracle JDBC固有のLOBLocatorを使用した、BLOBおよびCLOBデータ型に対するサポート

注意:

Thinドライバがラップされている非Oracle Thin JDBCドライバおよびアプリケーション環境では、プラットフォーム・インスタンスでsetShouldUseLocatorForLOBWrite(boolean)を使用し、LOBLocatorをオフにすることが可能です。

- Outer Join構文 (+) = のネイティブ・サポート

- ネイティブ順序付け (SELECT SEQ_NAME.NEXTVAL FROM DUAL)

- MaxRowsおよびFirstResultフィルタリングのネイティブSQL/ROWNUMサポート

- 階層Select (connect by prior)

- RETURNING句

- カスタム式関数(REGEXP_LIKE、LOCATE、ATAN2、LOG、CONCAT、SYSDATE (Date、Time、Today)、EXCEPT)

- 起動、パラメータ渡し、出力パラメータおよび出力カーソル用のPLSQLデータ型、ストアド関数、ストアド・プロシージャ構文。24.2.2項「EclipseLinkでのOracle PL/SQLの使用」を参照してください。

- SYSDATEおよびSYSTIMESTAMPを使用したオプティミスティック・ロックで使用するためのタイムスタンプ問合せ

- NCHAR、NSTRINGおよびNCLOBでのマルチバイトのサポート

- TIMESTAMP、TIMESTAMPTZおよびTIMESTAMPLTZのサポート

- XMLTypeフィールドおよびカスタムXSQL関数のOracle XML Databaseのサポート(extract、extractValue、existsNode、isFragment、getStringValおよびgetNumberVal)

- XDK XMLパーサー

- 履歴セッションでのフラッシュバック問合せ

- オブジェクト・リレーショナル・マッピング(ReferenceMapping、StructureMapping、NestedTableMapping、ArrayMapping、ObjectArrayMapping)

- Oracle AQ

- Oracle Real Application Clusters。24.2.5項「Oracle RACでのEclipseLinkの使用」を参照してください。

- Oracle Label Securityを含む仮想プライベート・データベース(VPD)。24.2.3項「Oracle仮想プライベート・データベースの使用」を参照してください。

- プロキシ認証。24.2.4項「Oracle Proxy Authenticationの使用」を参照してください。

24.2.2 EclipseLinkでのOracle PL/SQLの使用

EclipseLinkには、Oracle PL/SQLで使用するAPIが含まれています。このAPIは、org.eclipse.persistence.platform.database.oracle.plsqlパッケージとorg.eclipse.persistence.platform.database.oracle.annotationsパッケージにあります。

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

- Oracle PL/SQLストアド関数の実行

- Oracleストアド・プロシージャでのPL/SQL引数の処理

24.2.2.1 Oracle PL/SQLストアド関数の実行

Oracle PL/SQLのストアド関数は、RECORD型やTABLE型などの複雑なPL/SQLデータ型を返すために使用できます。PL/SQL型は、Oracle JDBCではサポートされていないので、これらの型はOracle OBJECT型やVARRAY型に変換する必要があります。JDBCでOBJECT型はjava.sql.Structとして返され、VARRAYはjava.sql.Array型として返されます。

PL/SQLストアド関数およびプロシージャの実行には、RECORDおよびTABLE型にミラーOBJECTおよびVARRAY型を定義する必要があります。OBJECT型は、@Struct注釈を使用し、@Entityまたは@Embeddableのいずれかで注釈されたクラスにマップできます。OBJECT型でIdが定義され、表にストアできる場合を除き、通常は@Embeddableの注釈がついたクラスが使用されます。ネストされるOBJECTおよびVARRAY型は、@Structureおよび@Array注釈を使用してマップされます。

PL/SQL型を使用してストアド関数を呼び出すには、PLSQLStoredFunctionCallクラスまたは@NamedPLSQLStoredFunctionQuery注釈を使用します。ストアド・プロシージャ用にPLSQLStoredProcedureCallクラスおよび@NamedPLSQLStoredProcedureQuery注釈もあります。複雑なPL/SQL型を返さないストアド関数およびプロシージャには、StoredFunctionCallクラス、@NamedStoredFunctionQuery注釈、StoredProcedureCallクラス、@NamedStoredProcedureQuery注釈を使用します。

24.2.2.1.1 主なタスク

Oracle PL/SQLストアド関数を実行するには、次の手順を実行します。

- タスク1: PL/SQLレコード・タイプを返すOracleストアド関数の作成

- タスク2: オブジェクト・タイプ・ミラーの定義

- タスク3: OBJECTタイプをマップするJavaクラスの定義

- タスク4: JpaEntityManagerを使用したPL/SQLストアド関数の実行

- タスク5: @NamedPLSQLStoredFunctionQueryを使用したストアド関数の定義

- タスク6: 問合せでのストアド関数の使用

24.2.2.1.2 タスク1: PL/SQLレコード・タイプを返すOracleストアド関数の作成

CREATE OR REPLACE PACKAGE EMP_PKG AS
TYPE EMP_REC IS RECORD (F_NAME VARCHAR2(30), L_NAME VARCHAR2(30),
SALARY NUMBER(10,2));
FUNCTION GET_EMP RETURN EMP_REC;
END EMP_PKG;

CREATE OR REPLACE PACKAGE BODY EMP_PKG AS
FUNCTION GET_EMP RETURN EMP_REC AS
P_EMP EMP_REC;
BEGIN P_EMP.F_NAME := 'Bob'; P_EMP.F_NAME := 'Smith'; P_EMP.SALARY := 30000;
RETURN P_EMP;
END;
END EMP_PKG;

24.2.2.1.3 タスク2: オブジェクト・タイプ・ミラーの定義

CREATE OR REPLACE TYPE EMP_TYPE AS OBJECT (F_NAME VARCHAR2(30),
L_NAME VARCHAR2(30), SALARY NUMBER(10,2))

24.2.2.1.4 タスク3: OBJECTタイプをマップするJavaクラスの定義

@Embeddable
@Struct(name="EMP_TYPE", fields={"F_NAME", "L_NAME", "SALARY"})
public class Employee {
@Column(name="F_NAME")
private String firstName;
@Column(name="L_NAME")
private String lastName;
@Column(name="SALARY")
private BigDecimal salary;
...
}

24.2.2.1.5 タスク4: JpaEntityManagerを使用したPL/SQLストアド関数の実行

import javax.persistence.Query;
import org.eclipse.persistence.platform.database.orcle.plsql.
PLSQLStoredFunctionCall;
import org.eclipse.persistence.queries.ReadAllQuery;

DataReadQuery databaseQuery = new DataReadQuery();
databaseQuery.setResultType(DataReadQuery.VALUE);
PLSQLrecord record = new PLSQLrecord();
record.setTypeName("EMP_PKG.EMP_REC");
record.setCompatibleType("EMP_TYPE");
record.setJavaType(Employee.class);
record.addField("F_NAME", JDBCTypes.VARCHAR_TYPE, 30);
record.addField("L_NAME", JDBCTypes.VARCHAR_TYPE, 30);
record.addField("SALARY", JDBCTypes.NUMERIC_TYPE, 10, 2);
PLSQLStoredFunctionCall call = new PLSQLStoredFunctionCall(record);
call.setProcedureName("EMP_PKG.GET_EMP");
databaseQuery.setCall(call);

Query query = ((JpaEntityManager)entityManager.getDelegate()).
createQuery(databaseQuery);
Employee result = (Employee)query.getSingleResult();

24.2.2.1.6 タスク5: @NamedPLSQLStoredFunctionQueryを使用したストアド関数の定義

@NamedPLSQLStoredFunctionQuery(name="getEmployee", functionName="EMP_PKG.GET_EMP",
returnParameter=@PLSQLParameter(name="RESULT", databaseType="EMP_PKG.EMP_REC"))
@Embeddable
@Struct(name="EMP_TYPE", fields={"F_NAME", "L_NAME", "SALARY"})
@PLSQLRecord(name="EMP_PKG.EMP_REC", compatibleType="EMP_TYPE",
javaType=Employee.class,fields={@PLSQLParameter(name="F_NAME"),
@PLSQLParameter(name="L_NAME"), @PLSQLParameter(name="SALARY",
databaseType="NUMERIC_TYPE")})

public class Employee {
...
}

24.2.2.1.7 タスク6: 問合せでのストアド関数の使用

Query query = entityManager.createNamedQuery("getEmployee");
Employee result = (Employee)query.getSingleResult();

24.2.2.2 Oracleストアド・プロシージャでのPL/SQL引数の処理

一般的に、ストアド・プロシージャは、StoredProcedureCallクラスのインスタンスを構築して処理します。ただし、引数がJDBCの仕様に準拠している必要があります。Oracle PL/SQLの引数(たとえば、BOOLEAN、PLS_INTEGER、PL/SQLレコードなど)を処理するには、PLSQLStoredProcedureCallクラスを使用します。

注意:

PLSQLStoredProcedureCallクラスは、Oracle8以上でのみサポートされています。

24.2.2.2.1 PLSQLStoredProcedureCallクラスの使用

次に、PLSQLStoredProcedureCallクラスを使用してPL/SQL引数を処理する方法を示します。この例は、次のターゲット・プロシージャに基づいています。

PROCEDURE bool_in_test(x IN BOOLEAN)

PLSQLStoredProcedureCallクラスを使用した例

import java.util.List;
import java.util.ArrayList;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.platform.database.jdbc.JDBCTypes;
import org.eclipse.persistence.platform.database.oracle.Oracle10Platform;
import org.eclipse.persistence.platform.database.oracle.OraclePLSQLTypes;
import org.eclipse.persistence.platform.database.oracle.PLSQLStoredProcedureCall;
import org.eclipse.persistence.queries.DataModifyQuery;
import org.eclipse.persistence.sessions.DatabaseLogin;
import org.eclipse.persistence.sessions.DatabaseSession;
import org.eclipse.persistence.sessions.Project;
import org.eclipse.persistence.sessions.Session;

public class TestClass {

public static String DATABASE_USERNAME = "username";
public static String DATABASE_PASSWORD = "password";
public static String DATABASE_URL = "jdbc:oracle:thin:@localhost:1521:ORCL";
public static String DATABASE_DRIVER = "oracle.jdbc.driver.OracleDriver";

public static void main(String[] args) {
Project project = new Project();
DatabaseLogin login = new DatabaseLogin();
login.setUserName(DATABASE_USERNAME);
login.setPassword(DATABASE_PASSWORD);
login.setConnectionString(DATABASE_URL);
login.setDriverClassName(DATABASE_DRIVER);
login.setDatasourcePlatform(new Oracle10Platform());
project.setDatasourceLogin(login);
Session s = project.createDatabaseSession();
s.setLogLevel(SessionLog.FINE);
((DatabaseSession)s).login();

PLSQLStoredProcedureCall call = new PLSQLStoredProcedureCall();
call.setProcedureName("bool_in_test");
call.addNamedArgument("X", OraclePLSQLTypes.PLSQLBoolean);
DataModifyQuery query = new DataModifyQuery();
query.addArgument("X");
query.setCall(call);
List queryArgs = new ArrayList();
queryArgs.add(Integer.valueOf(1));
s.executeQuery(query, queryArgs);
}
}

次に、無名PL/SQLブロックからターゲットのプロシージャを起動した場合のログの抜粋を示します。

...[EclipseLink Info]: 2007.11.23 01:03:23.890--DatabaseSessionImpl(15674464)--
Thread(Thread[main,5,main])-- login successful
[EclipseLink Fine]: 2007.11.23 01:03:23.968--DatabaseSessionImpl(15674464)--
Connection(5807702)--Thread(Thread[main,5,main])--
DECLARE
X_TARGET BOOLEAN := SYS.SQLJUTL.INT2BOOL(:1);
BEGIN
bool_in_test(X=>X_TARGET);
END;
bind => [:1 => 1]

注意:

DECLAREスタンザで、整数がPL/SQL BOOLEANタイプに変換されていることを確認してください(OUT BOOLEAN引数でも同じ変換が使用されています)。

24.2.2.2.2 非JDBC引数とJDBC引数の混合

ストアド・プロシージャに対して、通常のJDBCと非JDBC引数が混在している場合があります。少なくとも1つの引数が非JDBC型である場合はPLSQLStoredProcedureCallクラスを使用します。また、ターゲットのプロシージャが無名PL/SQLブロックから起動されるので、(長さ、スケール、精度の)JDBC型にはいくつか追加情報を追加する必要があります。この例は、次のターゲット・プロシージャに基づいています。

PROCEDURE two_arg_test(x IN BOOLEAN, y IN VARCHAR)

JDBC引数と非JDBC引数の混在の例

import org.eclipse.persistence.platform.database.jdbc.JDBCTypes;
...
PLSQLStoredProcedureCall call = new PLSQLStoredProcedureCall();
call.setProcedureName("two_arg_test");
call.addNamedArgument("X", OraclePLSQLTypes.PLSQLBoolean);
call.addNamedArgument("Y", JDBCTypes.VARCHAR_TYPE, 40);
DataModifyQuery query = new DataModifyQuery();
query.addArgument("X");
query.addArgument("Y");
query.setCall(call);
List queryArgs = new ArrayList();
queryArgs.add(Integer.valueOf(0));
queryArgs.add("test");
boolean worked = false;
String msg = null;
s.executeQuery(query, queryArgs);

次に、無名PL/SQLブロックからターゲットのプロシージャを起動した場合のログの抜粋を示します。

[EclipseLink Fine]: 2007.11.23 02:54:46.109--DatabaseSessionImpl(15674464)--
Connection(5807702)--Thread(Thread[main,5,main])--
DECLARE
X_TARGET BOOLEAN := SYS.SQLJUTL.INT2BOOL(:1);
Y_TARGET VARCHAR(40) := :2;
BEGIN
two_arg_test(X=>X_TARGET, Y=>Y_TARGET);
END;
bind => [:1 => 0, :2 => test]

24.2.2.2.3 INおよびOUT引数の処理

次に、次のターゲット・プロシージャに基づくINおよびOUT引数を両方含む、ストアド・プロシージャの例を示します。

PROCEDURE two_arg_in_out(x OUT BINARY_INTEGER, y IN VARCHAR) AS
BEGIN
x := 33;
END;

INおよびOUT引数の処理の例

import static org.eclipse.persistence.platform.database.oracle.OraclePLSQLTypes.
BinaryInteger;
...
PLSQLStoredProcedureCall call = new PLSQLStoredProcedureCall();
call.setProcedureName("two_arg_in_out");
call.addNamedOutputArgument("X", OraclePLSQLTypes.BinaryInteger);
call.addNamedArgument("Y", JDBCTypes.VARCHAR_TYPE, 40);
DataReadQuery query = new DataReadQuery();
query.setCall(call);
query.addArgument("Y");
List queryArgs = new ArrayList();
queryArgs.add("testsdfsdfasdfsdfsdfsdfsdfsdfdfsdfsdffds");
boolean worked = false;
String msg = null;
List results = (List)s.executeQuery(query, queryArgs);
DatabaseRecord record = (DatabaseRecord)results.get(0);
BigDecimal x = (BigDecimal)record.get("X");
if (x.intValue() != 33) {
System.out.println("wrong x value");
}

次に、無名PL/SQLブロックからターゲットのプロシージャを起動した場合のログの抜粋を示します。

[EclipseLink Fine]: 2007.11.23 03:15:25.234--DatabaseSessionImpl(15674464)--
Connection(5807702)--Thread(Thread[main,5,main])--
DECLARE
Y_TARGET VARCHAR(40) := :1;
X_TARGET BINARY_INTEGER;
BEGIN
two_arg_in_out(X=>X_TARGET, Y=>Y_TARGET);
:2 := X_TARGET;
END;
bind => [:1 => testsdfsdfasdfsdfsdfsdfsdfsdfdfsdfsdffds, X => :2]

注意:

実行時に引数をバインドする順序を変更する必要があります。無名PL/SQLブロックでは、最初にすべてのIN引数の順序マーカーを処理し(:1、:2)、次いでOUT引数を処理する必要があります。ブロックの中では、ターゲット・プロシージャの引数は正しい順序で処理されますが、バインド順序はDECLAREスタンザ内でターゲット・プロシージャの起動後で管理されます。

24.2.2.2.4 IN OUT引数の処理

無名PL/SQLブロックでは、IN OUT引数をネイティブで処理できません。引数はINの半分とOUTの半分の2つに分割する必要があります。次に、次のターゲット・プロシージャに基づいてIN OUT引数を処理するストアド・プロシージャの例を示します。

PROCEDURE two_args_inout(x VARCHAR, y IN OUT BOOLEAN) AS
BEGIN
y := FALSE;
END;

IN OUT引数の処理の例

...
PLSQLStoredProcedureCall call = new PLSQLStoredProcedureCall();
call.setProcedureName("two_args_inout");
call.addNamedArgument("X", JDBCTypes.VARCHAR_TYPE, 20);
call.addNamedInOutputArgument("Y", OraclePLSQLTypes.PLSQLBoolean);
DataReadQuery query = new DataReadQuery();
query.addArgument("X");
query.addArgument("Y");
query.setCall(call);
List queryArgs = new ArrayList();
queryArgs.add("test");
queryArgs.add(Integer.valueOf(1));
List results = (List)s.executeQuery(query, queryArgs);
DatabaseRecord record = (DatabaseRecord)results.get(0);
Integer bool2int = (Integer)record.get("Y");
if (bool2int.intValue() != 0) {
System.out.println("wrong bool2int value");
}

次に、無名PL/SQLブロックからターゲットのプロシージャを起動した場合のログの抜粋を示します。

[EclipseLink Fine]: 2007.11.23 03:39:55.000--DatabaseSessionImpl(25921812)--
Connection(33078541)--Thread(Thread[main,5,main])--
DECLARE
X_TARGET VARCHAR(20) := :1;
Y_TARGET BOOLEAN := SYS.SQLJUTL.INT2BOOL(:2);
BEGIN
two_args_inout(X=>X_TARGET, Y=>Y_TARGET);
:3 := SYS.SQLJUTL.BOOL2INT(Y_TARGET);
END;
bind => [:1 => test, :2 => 1, Y => :3]

注意:

Y引数は、:2および:3の順序マーカーを使用して2つに分割されます。

24.2.3 Oracle仮想プライベート・データベースの使用

EclipseLinkでは、Oracle仮想プライベート・データベース(VPD)をサポートしています。Oracle VPDはサーバーで実行される、精度の高い制御メカニズムです。Oracle VPDは、条件付きのSQL文を動的に追加して行レベルでデータ・アクセスを制限する形で、セキュリティ・ポリシーを表に関連付けます。セキュリティ・ポリシーは、独自に作成することも、Oracle Label Security (OLS)と呼ばれるOracleカスタム実装を使用することもできます。Oracle VPDの詳細は、『Oracle Databaseセキュリティ・ガイド』を参照してください。Oracle Label Securityの詳細は、『Oracle Label Security管理者ガイド』を参照してください。

マルチテナンシでOracle VPDを使用する方法の詳細は、14.4項「VPDマルチテナンシの使用」を参照してください。

EclipseLinkアプリケーションでOracle Database VPD機能を使用するには、独立したキャッシュを使用する必要があります。Oracle VPDを使用する表にマップされているエンティティには、独立済と構成されている識別子が必要です。また、通常排他接続を使用する必要があります。

Oracle VPDをサポートするには、永続性コンテキストのライフ・サイクルの間に起動されるセッション・イベント・ハンドラを実装する必要があります。どのようなセッション・イベント・ハンドラを実装する必要があるかは、Oracle Databaseプロキシ認証を使用しているかに依存します。

Oracle VPDとOracle Databaseのプロキシ認証

Oracle Databaseでプロキシ認証を使用すると、データベース内でOracle VPDに対するサポートを完全に設定することができます。つまり、セッション・イベント・ハンドラがSQLを実行するかわりに、プロキシsession_userを使用して、データベースがログイン・トリガー後に必要な設定を行います。

Oracleプロキシ認証の使用方法の詳細は、24.2.4項「Oracleプロキシ認証の使用」を参照してください。

Oracle Databaseのプロキシ認証を使用しないOracle VPD

Oracle Databaseのプロキシ認証を使用しない場合は、次のセッション・イベントでセッション・イベント・ハンドラを実装する必要があります。

- postAcquireExclusiveConnection: 独立セッションに専用接続が割り当てられ、独立セッション・ユーザーがデータベースとの通信に接続を使用する前に、Oracle VPDの設定を実行するために使用します。

- preReleaseExclusiveConnection: 独立セッションが解放され、ユーザーがデータベース通信を終了した後のVPDクリーン・アップの実行に使用します。

これらのハンドラの実装では、必要なユーザー資格証明は関連付られているセッションのプロパティから取得します。

24.2.4 Oracleプロキシ認証の使用

JPAとEclipseLinkは、通常、共有接続プールとともに中間層/サーバー環境で使用されます。接続プールでは、データベース接続が共有されるので、データベースに再接続するためのコストを回避できます。通常、ユーザーはアプリケーションにログインしますが、接続プール用には共有のログインが使用されるので、ユーザーは独自のデータベース・ログインは持ちません。これは、プロキシ・ユーザーを既存のデータベース接続に設定するメカニズムです。これは共有接続プールの使用を可能にする一方で、データベースにユーザー・コンテキストを与えます。

Oracleプロキシ認証は、EntityManagerオブジェクトに次の永続性ユニット・プロパティを使用して構成します。

- "eclipselink.oracle.proxy-type" : oracle.jdbc.OracleConnection.PROXYTYPE_USER_NAME, PROXYTYPE_CERTIFICATE, PROXYTYPE_DISTINGUISHED_NAME

- oracle.jdbc.OracleConnection.PROXY_USER_NAME : user_name

- oracle.jdbc.OracleConnection.PROXY_USER_PASSWORD : password

- oracle.jdbc.OracleConnection.PROXY_DISTINGUISHED_NAME

- oracle.jdbc.OracleConnection.PROXY_CERTIFICATE

- oracle.jdbc.OracleConnection.PROXY_ROLES

注意:

デフォルトで、この接続は書込みのみに使用され、読取りでは、共有接続プールが使用されます。読取りでもこの接続を使用するよう強制するには、eclipselink.jdbc.exclusive-connection.modeプロパティをAlwaysに設定しますが、これはアプリケーションで読取も書込みと同様に監査するかどうかによります。eclipselink.jdbc.exclusive-connection.is-lazyプロパティでは、接続を前もって接続するか、必要な初回時にのみ接続するかを構成します。書込みのみを監査する場合、書込みが発生しないかぎり、遅延接続により新しいデータベース接続を作成するコストが発生しません。

24.2.4.1 主なタスク

プロキシ認証を設定するには、EntityManagerオブジェクトを作成し、永続性ユニット・プロパティを設定します。次に例を3つ示します。

タスク: 書込みのみ監査

書込みのみを監査する場合のプロキシ認証の設定:

Map properties = new HashMap();
properties.put("eclipselink.oracle.proxy-type",
oracle.jdbc.OracleConnection.PROXYTYPE_USER_NAME);
properties.put(oracle.jdbc.OracleConnection.PROXY_USER_NAME, user);
properties.put(oracle.jdbc.OracleConnection.PROXY_USER_PASSWORD, password);
properties.put("eclipselink.jdbc.exclusive-connection.mode", "Transactional");
properties.put("eclipselink.jdbc.exclusive-connection.is-lazy", "true");
EntityManager em = factory.createEntityManager(properties);

タスク: 読取りおよび書込みの監査

読取りおよび書込みを監査する場合のプロキシ認証の設定:

Map properties = new HashMap();
properties.put("eclipselink.oracle.proxy-type",
oracle.jdbc.OracleConnection.PROXYTYPE_USER_NAME);
properties.put(oracle.jdbc.OracleConnection.PROXY_USER_NAME, user);
properties.put(oracle.jdbc.OracleConnection.PROXY_USER_PASSWORD, password);
properties.put("eclipselink.jdbc.exclusive-connection.mode", "Always");
properties.put("eclipselink.jdbc.exclusive-connection.is-lazy", "false");
EntityManager em = factory.createEntityManager(properties);

タスク: Java EEアプリケーションでのプロキシ認証の構成

JEEおよびJTAで管理されているエンティティ・マネージャを使用する場合、エンティティ・マネージャとJDBC接続はアプリケーションでは制御されないので、プロキシ・ユーザーとパスワードの指定はより困難になります。ただし、データベース接続を確立する前であれば、EntityManagerオブジェクトに永続性ユニット・プロパティを指定できます。

JPA 2.0を使用している場合、setProperty APIを使用することができます。

em.setProperty("eclipselink.oracle.proxy-type",
oracle.jdbc.OracleConnection.PROXYTYPE_USER_NAME);
em.setProperty(oracle.jdbc.OracleConnection.PROXY_USER_NAME, user);
em.setProperty(oracle.jdbc.OracleConnection.PROXY_USER_PASSWORD, password);
em.setProperty("eclipselink.jdbc.exclusive-connection.mode", "Always");
em.setProperty("eclipselink.jdbc.exclusive-connection.is-lazy", "false");

これ以外の場合は、getDelegate APIを使用します。

Map properties = new HashMap();
properties.put("eclipselink.oracle.proxy-type",
oracle.jdbc.OracleConnection.PROXYTYPE_USER_NAME);
properties.put(oracle.jdbc.OracleConnection.PROXY_USER_NAME, user);
properties.put(oracle.jdbc.OracleConnection.PROXY_USER_PASSWORD, password);
properties.put("eclipselink.jdbc.exclusive-connection.mode", "Always");
properties.put("eclipselink.jdbc.exclusive-connection.is-lazy", "false");
((org.eclipse.persistence.internal.jpa.EntityManagerImpl)em.getDelegate()).
setProperties(properties);

24.2.4.2 キャッシュおよびセキュリティ

デフォルトでは、EclipseLinkは共有(L2)オブジェクトのキャッシュを維持します。これは監査には問題がありませんが、Oracle VPDまたはユーザー・ベースのセキュリティが使用され、特定の表やクラスの読み取りができないようになっている場合、これらのセキュア・クラスのキャッシュを無効にする必要がある場合があります。共有キャッシュを無効にする方法の詳細は、「エンティティ・キャッシュの無効化」を参照してください。

データベース・ユーザーが読取りのセキュリティを確認することに慣れている場合、eclipselink.jdbc.exclusive-connection.modeプロパティをIsolatedに設定して、共有キャッシュが無効(独立)になっているクラスの読取りに対してのみユーザー接続使用されるようにします。

24.2.4.3 行レベルのセキュリティのためのOracle仮想プライベート・データベースの使用

Oracle仮想プライベート・データベース(VPD)機能では、Oracle Databaseで行レベルのセキュリティを確保できます。通常、データベース・セキュリティでは、表レベルでしかアクセス権限を設定できせん。行レベルでセキュリティを使用できる場合、各ユーザーは各表の別の行にアクセスできます。

Oracle VPDをサポートするには、EclipseLinkのOracleプロキシ認証機能を使用します。プロキシ・ユーザーは、行レベルでセキュリティがチェックされます。Oracle VPDを使用する場合、セキュリティで保護されたオブジェクトは共有できないので、これらの共有キャッシュを無効にすることも同様に重要です。共有キャッシュを無効にする方法の詳細は、「エンティティ・キャッシュの無効化」を参照してください。

24.2.5 Oracle RACでのEclipseLinkの使用

Oracle Real Application Clusters (RAC)では、Oracle Databaseを拡張して、別のサーバーの複数のデータベース・インスタンスを同時に使用して効率的にデータをストア、更新および取得できます。Oracle RACは、複数のサーバーをインスタンスおよび1つのグループとして管理するソフトウェアを提供します。アプリケーションはOracle RAC機能を使用して、接続のパフォーマンスおよび可用性を最大化し、接続の問題による停止時間を軽減します。アプリケーションの可用性およびパフォーマンスに対する要件は一様ではないため、それに応じてOracle RAC機能を実装する必要があります。Oracle RACの詳細は、『Oracle Real Application Clusters管理およびデプロイメント・ガイド』を参照してください。

Oracle DatabaseおよびOracle WebLogic Serverにはいずれも接続プールを実装でき、これでRACデータベースへ接続して様々なOracle RACの機能を利用できます。それらの機能には、高速接続フェイルオーバー(FCF)、実行時接続ロード・バランシング(RCLB)および接続アフィニティがあります。WebLogic Serverでは、RACが有効なデータベースに接続するために、アプリケーションでJDBCデータ・ソース(マルチ・データ・ソースまたはGridLinkデータ・ソース)が作成されます。スタンドアロン・アプリケーションでは、Universal Connection Pool (UCP) JDBC接続プールAPI (ucp.jar)が使用されて、データ・ソースが作成されます。いずれの接続プールも、実装するにはOracle Notification Serviceライブラリ(ons.jar)が必要です。このライブラリは、接続プールがRACイベントを登録およびリスニングする主要な手段です。これらのテクノロジに詳しくない場合は、『Oracle Universal Connection Pool for JDBC開発者ガイド』および『Oracle WebLogic Server JDBCデータ・ソースの管理』を参照してください。

この項は、Oracle JDBCドライバおよびOracle RACが有効なデータベースがあることが前提です。RACが有効なデータベースが動作し、接続URLがわかっている必要があります。また、ons.jarファイルを含むデータベースOracle Clientソフトウェアをダウンロードする必要があります。ucp.jarファイルは、Oracle Databaseに含まれています。

24.2.5.1 Java EEアプリケーションからのRACが有効なデータベースへのアクセス

この項のタスクは、Oracle WebLogic Serverに実装されている永続性アプリケーションからRACが有効なデータベースに接続するために使用します。

24.2.5.1.1 タスク1: マルチ・データ・ソースまたはGridLinkデータ・ソースの構築

Oracle RAC用にWebLogic Serverにデータ・ソースを構築する方法の詳細は、第3章「WebLogic ServerでのTopLink の使用」および『Oracle WebLogic Server JDBCデータ・ソースの管理』を参照してください。

24.2.5.1.2 タスク2: 永続性ユニットの構成

persistence.xmlファイルを編集し、永続性ユニットの構成にデータ・ソース名を含めます。次に例を示します。

<persistence-unit name="OrderManagement">
<jta-data-source>jdbc/MyOrderDB</jta-data-source>
...
</persistence-unit>

24.2.5.1.3 タスク3: 必要なJARを含める

ons.jarがWebLogic Serverのクラスパス内にあることを確認します。

24.2.5.2 スタンドアロン・アプリケーションからのRACが有効なデータベースへの接続

この項のタスクは、スタンドアロン永続性アプリケーションからRACデータベースに接続するために使用します。これらのタスクでは、高度なRACの機能で必要なUCPデータ・ソースを使用する方法を説明します。

24.2.5.2.1 タスク1: UCPデータ・ソースの作成

UCPデータ・ソースは、RACデータベースへの接続に使用します。データ・ソースでは高度なRAC構成を指定できます。UCPを使用した高度なRAC機能の使用方法の詳細は、『Oracle Universal Connection Pool for JDBC開発者ガイド』を参照してください。次の例では、データ・ソースを作成し、FCFを有効にし、ONSを構成します。

PoolDataSource datasource = PoolDataSourceFactory.getPoolDataSource();
datasource.setONSConfiguration(“nodes=host1:4200,host2:4200”);
datasource.setFastConnectionFailoverEnabled(true);
datasource.setConnectionFactoryClassName(“oracle.jdbc.pool.OracleDataSource”);
datasource.setURL(“jdbc:oracle:thin:@DESCRIPTION=
(LOAD_BALANCE=on)
(ADDRESS=(PROTOCOL=TCP)(HOST=host1)(PORT=1521))
(ADDRESS=(PROTOCOL=TCP)(HOST=host2)(PORT=1521))
(ADDRESS=(PROTOCOL=TCP)(HOST=host3)(PORT=1521))
(ADDRESS=(PROTOCOL=TCP)(HOST=host4)(PORT=1521))
(CONNECT_DATA=(SERVICE_NAME=service_name)))”);

RACやUCPの高度な機能を必要としないアプリケーションからは、EclipseLinkにネイティブな接続プールを使用してRACが有効なデータベースに接続できます。この場合、アプリケーションのpersistence.xmlファイルを編集し、永続性ユニット用にRACのURLの接続文字列を追加します。次に例を示します。

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
persistence_1_0.xsd" version="1.0">
<persistence-unit name="my-app" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.jdbc.driver"
value="oracle.jdbc.OracleDriver"/>
<property name="javax.persistence.jdbc.url"
value="jdbc:oracle:thin@(DESCRIPTION= "+ "(LOAD_BALANCE=on)"+
"(ADDRESS=(PROTOCOL=TCP)(HOST=rac_node) (PORT=1521))"+
"(ADDRESS=(PROTOCOL=TCP)(HOST=racnode2) (PORT=1521))"+
"(CONNECT_DATA=(SERVICE_NAME=service_name))")"/>
<property name="javax.persistence.jdbc.user" value="user_name"/>
<property name="javax.persistence.jdbc.password" value="password"/>
</properties>
</persistence-unit>
</persistence>

永続性ユニットを使用するには、次のようにEntityManagerFactoryをインスタンス化します。

Persistence.createEntityManagerFactory("my-app");

24.2.5.2.2 タスク2: UCPデータ・ソースの使用

UCPデータ・ソースを使用するには、次のようにEntityManagerFactoryをインスタンス化し、データ・ソースを渡します。

Map properties = new HashMap();
properties.add("javax.persistence.nonJtaDataSource", datasource);
Persistence.createEntityManagerFactory(properties);

24.2.5.2.3 タスク3: 必要なJARを含める

ucp.jarおよびons.jarの両方がアプリケーションのクラスパスに含まれていることを確認します。

24.2.6 Oracle Spatial and Graphの使用

EclipseLinkには、Oracle DatabaseでOracle Spatial and Graphデータを問い合せる際のサポートが追加されています。Oracle Spacial and Graphは、アプリケーションで位置を有効にするために使用できます。これには、空間データおよび空間分析、物理グラフ、論理グラフ、ネットワーク・グラフ、ソーシャル・グラフおよびセマンティック・グラフ・アプリケーション用の高度な機能が含まれています。空間フィーチャは、Oracle Databaseへの空間フィーチャの集合の格納、検索、更新および問合せを容易にするスキーマおよびファンクションを提供します。Oracle Spacial and Graphアプリケーションの開発の詳細は、『Oracle Spatial and Graph開発者ガイド』を参照してください。WebLogic ServerでOracle Spatial and Graphを使用する方法の詳細は、第3章「タスク7: Oracle Databaseの高度な機能を使用するためのドメインの拡張」を参照してください。

EclipseLinkアプリケーションでは、Oracle Spacial and Graphの演算子を使用する式を構築できます。詳細は、org.eclipse.persistence.expressions.spatial APIを参照してください。次に例を示します。

ExpressionBuilder builder = new ExpressionBuilder();
Expression withinDistance = SpatialExpressions.withinDistance(myJGeometry1,
myJGeometry2, "DISTANCE=10");
session.readAllObjects(GeometryHolder.class, withinDistance);

次の例では、oracle.spatial.geometry.JGeometryオブジェクトが必要です。EclipseLinkのorg.eclipse.persistence.platform.database.oracle.converters.JGeometryConverterコンバータを使用し、Oracle Databaseから読み書きされるようにJGeometryオブジェクトを変換します。JGeometryConverterオブジェクトはaddStructConverter(StructConverter)メソッドまたはsessions.xmlファイルに指定して、Oracle Databaseプラットフォームに追加する必要があります。JGeometryタイプもクラスパスで存在する必要があります。

次に、Oracle Spatialに問合せを実行するために、FUNCTION JPA拡張を使用する方法を示します。FUNCTIONの拡張の詳細は、『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』を参照してください。

SELECT a FROM Asset a, Geography geo WHERE geo.id = :id AND a.id IN :id_list AND
FUNCTION('ST_INTERSECTS', a.geometry, geo.geometry) = 'TRUE'

SELECT s FROM SimpleSpatial s WHERE FUNCTION('MDSYS.SDO_RELATE', s.jGeometry,
:otherGeometry, :params) = 'TRUE' ORDER BY s.id ASC

24.3 その他の参考資料

この章で説明しているソリューションのその他の参考資料については、次のリンクを参照してください。

- 『Oracle TopLink Java APIリファレンス』

- 『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』

- Oracle Database JDBC Java APIリファレンス

- 『Oracle Database PL/SQL言語リファレンス』

- 『Oracle Databaseセキュリティ・ガイド』

- 『Oracle Label Security管理者ガイド』

- Oracle WebLogic ServerのJDBCデータ・ソースの管理

- 『Oracle Real Application Clusters管理およびデプロイメント・ガイド』

- 『Oracle Universal Connection Pool for JDBC開発者ガイド』

- 『Oracle Spatial and Graph開発者ガイド』

オラクル社の法律上の注意点について

コピーライトについて

Copyright © 1994-2014, Oracle and/or its affiliates.All rights reserved.

商標と登録商標について

OracleおよびJavaはOracle Corporationおよびその関連企業の登録商標です。その他の名称は、それぞれの所有者の商標または登録商標です。

Intel、Intel Xeonは、Intel Corporationの商標または登録商標です。すべてのSPARCの商標はライセンスをもとに使用し、SPARC International, Inc.の商標または登録商標です。AMD、Opteron、AMDロゴ、AMD Opteronロゴは、Advanced Micro Devices, Inc.の商標または登録商標です。UNIXは、The Open Groupの登録商標です。

ライセンス制約の保証と結果的に生じる損害の免責

このソフトウェアおよび関連ドキュメントの使用と開示は、ライセンス契約の制約条件に従うものとし、知的財産に関する法律により保護されています。ライセンス契約で明示的に許諾されている場合もしくは法律によって認められている場合を除き、形式、手段に関係なく、いかなる部分も使用、複写、複製、翻訳、放送、修正、ライセンス供与、送信、配布、発表、実行、公開または表示することはできません。このソフトウェアのリバース・エンジニアリング、逆アセンブル、逆コンパイルは互換性のために法律によって規定されている場合を除き、禁止されています。

保証免責

ここに記載された情報は予告なしに変更される場合があります。また、誤りが無いことの保証はいたしかねます。誤りを見つけた場合は、オラクル社までご連絡ください。

制限付権利

このソフトウェアまたは関連ドキュメントを、米国政府機関もしくは米国政府機関に代わってこのソフトウェアまたは関連ドキュメントをライセンスされた者に提供する場合は、次の通知が適用されます。

U.S. GOVERNMENT END USERS: Oracle programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, delivered to U.S. Government end users are "commercial computer software" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations.As such, use, duplication, disclosure, modification, and adaptation of the programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, shall be subject to license terms and license restrictions applicable to the programs.No other rights are granted to the U.S. Government.

危険な用途への使用について

このソフトウェアもしくはハードウェアは様々な情報管理アプリケーションでの一般的な使用のために開発されたものです。このソフトウェアもしくはハードウェアは、危険が伴うアプリケーション（人的傷害を発生させる可能性があるアプリケーションを含む）への用途を目的として開発されていません。このソフトウェアもしくはハードウェアを危険が伴うアプリケーションで使用する際、安全に使用するために、適切な安全装置、バックアップ、冗長性（redundancy）、その他の対策を講じることは使用者の責任となります。このソフトウェアもしくはハードウェアを危険が伴うアプリケーションで使用したことに起因して損害が発生しても、オラクル社およびその関連会社は一切の責任を負いかねます。

第三者のコンテンツ、製品、サービスに対する免責事項

このソフトウェアまたはハードウェア、そしてドキュメントは、第三者のコンテンツ、製品、サービスへのアクセス、あるいはそれらに関する情報を提供することがあります。オラクル社およびその関連会社は、第三者のコンテンツ、製品、サービスに関して一切の責任を負わず、いかなる保証もいたしません。オラクル社およびその関連会社は、第三者のコンテンツ、製品、サービスへのアクセスまたは使用によって損失、費用、あるいは損害が発生しても一切の責任を負いかねます。

ドラフトのアルファ版およびベータ版ドキュメントについて

このドキュメントが試作版の場合:

このドキュメントは試作版であり、デモおよび暫定使用のみを目的としたものです。このソフトウェアを使用するハードウェアに限定するものではありません。オラクル社およびその関連会社は、このドキュメントに関して一切の責任を負わず、いかなる保証もいたしません。また、このドキュメントを使用したことによって損失、費用、あるいは損害が発生しても、一切の責任を負いかねます。