ヘッダーをスキップ
Oracle® Fusion Middleware Oracle TopLinkソリューション・ガイド
12c (12.1.2)
E47993-02
  目次へ移動
目次

前
 
 

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

この章では、特にOracle Databaseプラットフォームをサポートするよう設計されたOracle TopLinkのEclipseLinkの機能を理解して使用する方法を説明します。

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

ユース・ケース

Oracle TopLinkには、すべてのデータベースに対応するよう設計された永続性ソリューションが用意されています。ただし、アプリケーションでOracle Databaseプラットフォームを使用する計画の場合は、Oracle Databaseに対する高度なサポートを利用できます。

解決方法

このソリューションは、TopLinkの様々なAPIやOracle製品によって実現されています。使用しているOracle Databaseの機能や製品に基づいて、アプリケーションで様々なOracle TopLinkのAPIの実装を選択します。

コンポーネント

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 ソリューションの実装

この項では、テクノロジごとのソリューションをまとめています。このようにまとめることにより、開発者はソリューションの様々な部分を簡単に理解して、実装する部分を具体的に選択できます。

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

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[]DateTimeTimestampおよび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_LIKELOCATEATAN2LOGCONCATSYSDATE (Date、Time、Today)、EXCEPT)

  • 起動、パラメータ渡し、出力パラメータおよび出力カーソル用のPLSQLデータ型、ストアド関数、ストアド・プロシージャ構文。24.2.2項「EclipseLinkでのOracle PL/SQLの使用」を参照してください。

  • SYSDATEおよびSYSTIMESTAMPを使用したオプティミスティック・ロックで使用するためのタイムスタンプ問合せ

  • NCHARNSTRINGおよびNCLOBでのマルチバイトのサポート

  • TIMESTAMPTIMESTAMPTZおよびTIMESTAMPLTZのサポート

  • XMLTypeフィールドおよびカスタムXSQL関数のOracle XML Databaseのサポート(extractextractValueexistsNodeisFragmentgetStringValおよび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パッケージにあります。

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

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として返され、VARRAYjava.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ストアド関数を実行するには、次の手順を実行します。

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の引数(たとえば、BOOLEANPLS_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 その他の参考資料

この章で説明しているソリューションのその他の参考資料については、次のリンクを参照してください。