セッションの最も重要な機能の1つは、データ・ソースへのアクセスを提供することです。この章では、データ・ソースへのアクセスに固有のセッション・コンポーネントについて説明します。
この章では、次のようなEclipseLinkに特有のデータ・アクセスの概念について説明します。
EclipseLinkのトランザクション・データ・ソースは、接続プールがトランザクション・サービス(アプリケーション・サーバー制御トランザクションやJTAトランザクションなど)によって管理される場合、外部管理されます。JTA管理のデータ・ソースまたは接続プールは、一般的にJava EEアプリケーションで使用され、通常はEJBアプリケーションで必要になります。外部管理の接続プールは、次のように使用します。
ExternalTransactionController
を使用するようにセッションを構成し、EclipseLinkの作業ユニットを外部トランザクション・サービスに統合します。
external-transaction-control
オプションを使用して、接続のログインを指定し、接続が外部コントローラによって維持されていることをEclipseLinkに通知します。
状況によっては、トランザクションのオーバーヘッドを回避するために、JTA以外の接続プールを使用するようにEclipseLinkの読取り接続プールまたはシーケンス接続プールを構成する必要があります。
セッションに関連付けられたログイン(存在する場合)によって、EclipseLinkランタイムがプロジェクトのデータ・ソースに接続する方法が決まります。
ログインには、認証、接続プールの使用、および外部トランザクション・コントローラの使用などのデータソース・アクセスの詳細が含まれます。Login
は、データ・ソース・プラットフォームを所有します。
データ・ソース・プラットフォームには、バインディング、ネイティブSQLの使用、バッチ書込みの使用、順序付けなどの特定のデータ・ソースに固有のオプションが含まれます。
データ・ソースに永続化しないプロジェクトの場合、ログインは必要ありません。データ・ソースに永続化するプロジェクトの場合、ログインは常に必要です。
ログインは様々なロールで使用できます。ログインのロールにより、ログインを作成する場所と方法が決まります。選択するログインのロールは、作成対象のプロジェクトのタイプやログインの使用目的によって異なります。
データ・ソースに永続化するプロジェクト・タイプごとに、独立したセッション・ログイン・タイプがあります。
XMLログインは存在しません。EclipseLink XMLプロジェクトはXMLデータ・トランスフォーメーションに対する非永続的なインメモリー・オブジェクト用として使用されるため、ログインするデータ・ソースは存在しません。
リレーショナル・データベースにアクセスするプロジェクトを作成する場合、DatabaseLogin
を使用してプロジェクトを構成する必要があります。DatabasePlatform
を選択することによって、特定のタイプのデータベースについてプロジェクトをさらにカスタマイズできます。
EclipseLinkは、データ・ソース・プラットフォームのクラスを使用して基礎となるデータ・ソースの詳細を抽出します。データ・ソース・プラットフォームは、プロジェクトのLogin
によって所有されます。
ほとんどのプラットフォーム・オプションを構成するには、修正メソッドまたはpreLogin
イベント・リスナーを使用する必要があります。
EclipseLinkでは、Structured Query Language (SQL)を使用してデータベースと対話します。各データベース・プラットフォームでは、基本SQL言語の独自のバリエーションが使用されるため、EclipseLinkでは、データベースとの通信に使用するSQLを調整し、アプリケーションが円滑に実行されるようにする必要があります。
選択するデータベース・プラットフォームのタイプによって、使用されるJava Database Connectivity (JDBC)ドライバのタイプなど、EclipseLinkランタイムがデータベースにアクセスする場合の特定の手段が決定されます。JDBCは、Javaアプリケーションによるデータベースへのアクセスを可能にするアプリケーション・プログラミング・インタフェース(API)です。EclipseLinkリレーショナル・プロジェクトは、データベースを対象にオブジェクトの読取りや書込みを行うために、JDBC接続に依存します。EclipseLinkアプリケーションでは、アプリケーション・アーキテクチャに応じて個別のJDBC接続を使用するか、JDBC接続プールを使用します。
EclipseLinkには、ターゲット・データベースに応じてプロジェクトをカスタマイズするために様々なデータベース固有のプラットフォームが用意されています。サポートされているデータベース・プラットフォームのリストについては、A.1項「データベースのサポート」を参照してください。
データベース・プラットフォームは、すべてのセッションに対してプロジェクト・レベルで指定するか、このプロジェクト・レベルの構成をセッション・レベルでオーバーライドします。
認証は、データ・ソースがユーザーのアイデンティティを検証し、そのユーザーに特定のアクションを実行するために十分な権限があるかどうかを確認するための手段です。認証は、データ・セキュリティ、ユーザーのアカウンタビリティおよび監査において中心的な役割を果たします。
2層アプリケーションの場合、通常は単純なJDBC認証で十分です。
次の項では、異なる認証方針について説明します。
ユーザー名とパスワードを使用してEclipseLinkデータベース・ログインを構成すると、EclipseLinkでは、アプリケーションで使用するように構成されているJDBCドライバにこれらの資格証明が提供されます。
デフォルトでは、EclipseLinkは、JCE暗号化を使用した暗号形式でsessions.xml
ファイルに対してパスワードの書込みおよび読取りを行います。オプションで、異なる暗号化クラスを構成できます。
EclipseLinkでは、Oracle JDBCドライバおよび外部接続プールのみを使用した、Java SEアプリケーションおよびJava EEアプリケーションのOracle Databaseでのプロキシ認証がサポートされます。
注意: EclipseLinkでは、JTAによるOracle Databaseのプロキシ認証はサポートしていません。 |
Oracleデータベースのプロキシ認証には、次のようなセキュリティ上の利点があります。
中間層が代理として接続可能なユーザーや、中間層がユーザーから引き受けるロールの制御による、制限付きの信頼モデル
Oracle Call Interface (OCI)およびシックJDBCを介したユーザー・セッションのサポートや、クライアント再認証のオーバーヘッドの解消による、スケーラビリティ
データベースを介した実際のユーザーのアイデンティティの保持や、実際のユーザーのかわりに実行されるアクションの監査の有効化による、アカウンタビリティ
ユーザーがデータベースに把握される環境や、ユーザーがデータベースに認識されない単なるアプリケーション・ユーザーにすぎない環境のサポートによる、柔軟性
注意: Oracleデータベースは、3層でのプロキシ認証のみをサポートしています。複数の中間層間におけるプロキシ認証はサポートしていません。 |
Oracleデータベースでの認証の詳細は、『Oracle Databaseセキュリティ・ガイド』の多層環境でのユーザー・アイデンティティの保持に関する項を参照してください。
プロキシ認証を使用するようにEclipseLinkデータベース・ログインを構成し、次の操作を実行します。
3層アーキテクチャでの複雑な認証に対応する(クライアント対中間層および中間層対データベースの認証、中間層を介したデータベースへのクライアントの再認証など)。
汎用プール・ユーザーではなくデータベース操作用の特定のユーザーを使用して、データベースの(トリガーおよびストアド・プロシージャに関するものを含む)監査情報を向上させる。
ストアド・プロシージャでセッション・コンテキストに直接ユーザー情報を設定するのではなく、プロキシ・ユーザーを使用してVPD/OLS構成を簡略化する。
選択する認証のタイプとは関係なく、EclipseLinkは、すべてのデータベース操作に関連するユーザーの名前をログに記録します。例8-1は、CONFIG
レベルのEclipseLinkログを示し、ServerSession
がサンプル・ユーザーscottのメイン接続を介して接続し、ClientSession
がプロキシ接続jeffを使用しています。
例8-1 Oracle Databaseのプロキシ認証のログ
[TopLink Config]--ServerSession(13)--Connection(14)--Thread(Thread[main,5,main])--connecting(DatabaseLogin( platform=>Oracle9Platform user name=> "scott" connector=>OracleJDBC10_1_0_2ProxyConnector datasource name=>DS)) [TopLink Config]--ServerSession(13)--Connection(34)--Thread(Thread[main,5,main])--Connected: jdbc:oracle:thin:@localhost:1521:orcl User: SCOTT [TopLink Config]--ClientSession(53)--Connection(54)--Thread(Thread[main,5,main])--connecting(DatabaseLogin(platform=>Oracle9Platform user name=> "scott" connector=>OracleJDBC10_1_0_2ProxyConnector datasource name=>DS)) [TopLink Config]--ClientSession(53)--Connection(56)--Thread(Thread[main,5,main])--Connected: jdbc:oracle:thin:@localhost:1521:orcl User: jeff
データベース・サーバーによっては、別のユーザー監査オプションが用意されている場合があります。詳細は、データベース・サーバーのドキュメントを参照してください。
または、監査目的でデータベース・スキーマと組み合せてEclipseLink作業ユニットを使用することも検討してください。
接続は、アプリケーションで使用するように構成されたドライバを介してデータ・ソースにアクセスする方法を提供するオブジェクトです。リレーショナル・プロジェクトでは、JDBCを使用してデータ・ソースに接続し、EISプロジェクトではJCAを使用します。EclipseLinkでは、インタフェースorg.eclipse.persistence.internal.databaseaccess.Accessor
を使用してデータ・ソース接続をラップします。このインタフェースは、特定のイベントからアクセス可能です。
通常、サーバー・セッションを使用する場合、EclipseLinkは、読取りと書込みの両方に対して異なる接続を使用します。このため、読取りには非トランザクション接続を使用し、必要ない場合は接続を維持しないようにできます。
デフォルトでは、EclipseLinkサーバー・セッションは、接続を遅延して(作業ユニットのコミット操作時にのみ)取得します。または、クライアント・セッションの取得時に書込み接続を取得するようにEclipseLinkを構成できます。
接続は、内部または外部の接続プールから割り当てることができます。
接続プールは、1つ以上のクライアントのかわりにデータソース接続の共有コレクション(プール)を作成および保持するサービスです。接続プールは、リクエストに基づいてプロセスに接続を提供し、プロセスが接続の使用を終了すると、接続をプールに返します。接続は、プールに返されると、他のプロセスで使用できます。データ・ソースへの接続の確立には時間がかかるため、接続プールのこのような接続を再使用してパフォーマンスを向上できます。
EclipseLinkは、接続プールを使用して、サーバーおよびクライアント・セッションで使用される接続を管理および共有します。この機能により、必要な接続数が減り、アプリケーションで多くのクライアントをサポートできるようになります。
EclipseLinkで提供される内部接続プール、またはJDBCドライバまたはJava EEコンテナで提供される外部接続プールを使用するようにセッションを構成できます。
EclipseLinkアプリケーションの接続プールは、読取り、書込み、順序付け、およびその他のアプリケーション固有の機能などの様々な目的に使用できます。
この項では、次の接続プールのタイプについて説明します。
Java EE以外のアプリケーションでは、通常、内部接続プールを使用します。デフォルトでは、EclipseLinkセッションは内部接続プールを使用します。
内部接続プールを使用して、デフォルト(書込み)および読取りの接続プールを構成したり、オブジェクト・アイデンティティまたは他の目的のために追加の接続プールを作成することもできます。
内部接続プールを使用すると、表示専用でデータの変更が頻繁ではないデータを読み取るアプリケーション用の読取り接続の作成を最適化できます。
Java EEアプリケーションでは、通常、外部接続プールを使用します。
外部トランザクション・コントローラ(JTA)を使用する場合、外部接続プールを使用してJTAと統合する必要があります。
外部接続プールを使用して、Javaを通じてデフォルト(書込み)および読取りの接続プールを構成したり、オブジェクト・アイデンティティまたは他の目的のために追加の接続プールを作成することもできます。
サーバー・セッションでは、読取り接続プールと書込み接続プールが提供されます。これらは異なるプールとするか、または(外部接続プーリングを使用する場合は)同じ接続プールとすることが可能です。
すべての読取り問合せは読取り接続プールからの接続を使用し、データ・ソースに変更を書き込むすべての問合せは書込み接続プールからの接続を使用します。デフォルト(書込み)および読取り接続プールの属性を構成できます。
新規接続が確立されるたびに、セッションのDatasourceLogin
に指定した接続構成がEclipseLinkにより使用されます。また、外部トランザクション・コントローラを使用する場合、必要に応じて読取り接続プールごとに個別の接続構成を定義することにより、余計なオーバーヘッドが発生しないようにできます。
オブジェクト・アイデンティティを保持するうえで重要なのは、各インスタンスを区別するために一意の値の割当ての順序付け管理をすることです。詳細は、9.2項「キャッシュのタイプとサイズについて」を参照してください。
順序付けには、データ・ソースによって管理される特別な順序リソースの読取りと書込みが含まれます。
デフォルトで、EclipseLinkには個別トランザクションの順序操作が含まれます。これによって、順序リソースのデッドロックを発生させる可能性のある書込みトランザクション中の複雑な操作を回避します。ただし、外部トランザクション・コントローラ(JTAデータ・ソースや接続プールなど)を使用する場合、EclipseLinkでは、順序付けで異なるトランザクションを使用できません。シーケンス接続プールを使用して、順序付け用に非JTAトランザクション・プールを構成します。これは、(ネイティブ順序付けではなく)表の順序付けの場合にのみ必要です。
各サーバー・セッションで、EclipseLinkが順序付け用に排他的に使用する、シーケンス接続プールと呼ばれる1つの接続プールを作成できます。シーケンス接続プールによって、EclipseLinkは、リクエストの取得元であるトランザクションの外部にある新しいオブジェクト識別子に対するリクエストに対応できます。これによって、EclipseLinkは、順序リソースに対する更新を即座にコミットし、デッドロックを回避できます。
注意: シーケンス接続プールの使用時に元のトランザクションが失敗しても、順序操作はロールバックされません。 |
次のような場合は、シーケンス接続プールを使用する必要があります。
表の順序付け(非ネイティブ順序付け)を使用する場合。
外部トランザクション・コントローラ(JTA)を使用する場合。
次のような場合は、シーケンス接続プールを使用しないようにする必要があります。
順序付けを使用しないか、データ・ソースのネイティブ順序付けを使用する場合。
デッドロックを回避するために順序表を構成した場合。
非JTAデータ・ソースを使用する場合。
セッションでEclipseLinkの内部接続プールを使用する場合、アプリケーションの任意の目的のために使用できる1つ以上の接続プールを作成できます。これらは名前付き接続プールと呼ばれ、名前を自由に付け、任意の目的のために使用できます。
通常、これらの名前付き接続プールを使用して、様々なセキュリティ・レベルのプールを提供します。たとえば、デフォルト接続プールの場合は特定の表にのみアクセスできますが、管理接続プールの場合はすべての表にアクセスできます。
データ・パーティション化によって、アプリケーションでは、そのデータを複数のデータベース・マシン全体に拡張できます。EclipseLinkでは、エンティティ・レベルでデータ・パーティション化がサポートされ、同じクラスのエンティティ・インスタンスの異なるセットを、異なる物理データベースまたはデータベース・クラスタ内の異なるノードに格納できます。通常のデータベースとクラスタ化されたデータベースの両方がサポートされます。データは、水平方向と垂直方向の両方にパーティション化できます。
パーティション化は、エンティティ、リレーションシップ、問合せまたは永続性ユニットで有効化できます。
データ・パーティション化を構成するには、@Partitioned
注釈および1つ以上のパーティション化ポリシー注釈を使用します。異なる種類のポリシーを定義するための注釈は、次のとおりです。
@HashPartitioning
: オブジェクトのフィールド値(オブジェクトのID、場所またはテナントなど)のハッシュによってデータベース・クラスタに対するアクセスをパーティション化します。ハッシュは、接続プール/ノードのリストに索引付けされます。そのハッシュ値を持つオブジェクトのすべての書込みまたは読取りリクエストは、同じサーバーに送信されます。問合せにパラメータとしてハッシュ・フィールドが含まれない場合、それはすべてのサーバーに送信して結合するか、セッションのデフォルト動作に任せることができます。
@PinnedPartitioning
: リクエストを単一の接続プール/ノードに固定します。これによって、垂直パーティション化が可能になります。
@RangePartitioning
: オブジェクトのフィールド値(オブジェクトのID、場所またはテナントなど)によってデータベース・クラスタに対するアクセスをパーティション化します。各サーバーには値の範囲が割り当てられます。その値を持つオブジェクトのすべての書込みまたは読取りリクエストは、同じサーバーに送信されます。問合せにパラメータとしてフィールドが含まれない場合、それはすべてのサーバーに送信して結合するか、セッションのデフォルト動作に任せることができます。
@ReplicationPartitioning
: 接続プール/ノードのセットにリクエストを送信します。このポリシーは、データベース・マシンのクラスタ全体にデータをレプリケートするためのものです。変更問合せのみがレプリケートされます。
@RoundRobinPartitioning
: 接続プール/ノードのセットにラウンドロビン法でリクエストを送信します。これは、データベース・マシンのクラスタ全体に読取り問合せをロード・バランシングするためのものです。この場合、各マシンで全データベースをレプリケートする必要があるため、パーティション化はサポートされません。データは読取り専用にするか、書込みをレプリケートする必要があります。
@UnionPartitioning
: すべての接続プールに問合せを送信し、結果を結合します。これは、パーティション化の使用時にパーティション全体にわたる問合せまたはリレーションシップ(ManyToMany
クロス・パーティション化リレーションシップなど)を対象とします。
@ValuePartitioning
: オブジェクトのフィールド値(オブジェクトの場所またはテナントなど)によってデータベース・クラスタに対するアクセスをパーティション化します。各値には特定のサーバーが割り当てられます。その値を持つオブジェクトのすべての書込みまたは読取りリクエストは、同じサーバーに送信されます。問合せにパラメータとしてフィールドが含まれない場合、それはすべてのサーバーに送信して結合するか、セッションのデフォルト動作に任せることができます。
@Partitioning
: カスタム・パーティション化ポリシーによってデータベース・クラスタに対するアクセスをパーティション化します。PartitioningPolicy
クラスを提供して実装する必要があります。
パーティション化ポリシーは、永続性ユニットでグローバルに名前付けされたオブジェクトで、複数のディスクリプタまたは問合せで再利用できます。これによって、特にJPAの注釈およびメタデータを使用する場合に構成の利便性が向上します。
永続性ユニットのプロパティでは、読取り、書込み、順序用の既存の構成に加え、名前付き接続プールを追加できます。名前付き接続プールは、データベース・クラスタのノードごとに定義する必要があります。
トランザクションで複数のパーティションにあるデータを変更する場合、JTAを使用してデータの2フェーズ・コミットを保証する必要があります。1つのトランザクションで単一のノードのみを使用するように、EntityManager
で排他接続を構成することもできます。
一部のデータベースでは、複数のマシン全体にわたるデータベースのクラスタリングがサポートされます。Oracle RACでは、単一のデータベースを複数の異なるサーバー・ノードに拡張できます。Oracle RACでは、表およびノードでデータのパーティション化もサポートされます。データベース・クラスタでは、クラスタ内の任意のノードからどのデータにもアクセスできます。ただし、特定のノードへのデータ・アクセスをパーティション化する方が、ノード間通信が減少するため、通常はより効率的です。
EclipseLinkのパーティション化をクラスタ・データベースと組み合せると、ノード間通信を減少させ、スケーラビリティを向上できます。
データベース・クラスタとともにパーティション化を使用する場合、次の要件があります。
パーティション・ポリシーではレプリケーションを有効化しないでください(データベース・クラスタではすべてのノードでデータを使用可能にするため)。
パーティション・ポリシーでは論理和を使用しないでください(データベース・クラスタではどのノードからも完全な問合せ結果が返されるため)。
データ・ソースおよびEclipseLinkの接続プールは、クラスタ内のノードごとに定義する必要があります。
アプリケーションのデータ・アクセスおよびデータ・パーティション化は、各トランザクションが単一のノードにのみアクセスするように設計する必要があります。
単一トランザクションでの複数ノードの使用および2フェーズ・コミットを回避するため、EntityManagerでは排他接続の使用をお薦めします。