7 サーバー側内部ドライバ

この章の構成は、次のとおりです。

7.1 サーバー側内部ドライバの概要

サーバー側内部ドライバは、Oracle DatabaseとOracle Java仮想マシン(Oracle JVM)とも呼ばれる埋込みJava仮想マシンに結び付けられています。このドライバは、データベースと同じプロセスの一部として動作します。また、デフォルトのセッション(Oracle JVMが起動されたセッションと同じセッション)内で動作します。各Oracle JVMセッションには、存在するデータベース・セッションに対して1つの暗黙的なネイティブ接続があります。この接続は概念的で、Javaオブジェクトではありません。これはこのセッションに固有な側面であり、JVM内でオープンまたはクローズできません。

サーバー側内部ドライバはデータベース・サーバー内で動作するよう最適化されており、このドライバを使用するとローカル・データベース上のSQLデータおよびPL/SQLサブプログラムに直接アクセスできます。JVM全体は、データベースおよびSQLエンジンと同じアドレス空間内で動作します。SQLエンジンへのアクセスはファンクション・コールです。これによって、Java Database Connectivity(JDBC)アプリケーションのパフォーマンスが向上し、SQLエンジンへのアクセスにリモートOracle Netコールを実行するよりも速くなります。

サーバー側内部ドライバは、クライアント側ドライバと同じ機能、Application Program Interface(API)およびOracle拡張機能をサポートします。これにより、アプリケーションのパーティション化が非常に簡単になります。たとえば、データ集中処理型のJavaアプリケーションがある場合は、アプリケーション固有のコールを修正しなくても、パフォーマンスを向上させるために簡単にデータベース・サーバーに移動できます。

7.2 データベースへの接続

前の項で説明したように、サーバー側内部ドライバはデフォルトのセッション内で動作します。したがって、すでに接続された状態になっています。デフォルト接続にアクセスするには、次の2つのメソッドを使用できます。

  • 次のいずれかの形式をURL文字列として、OracleDataSource.getConnectionメソッドを使用します。

    • jdbc:oracle:kprb

    • jdbc:default:connection

    • jdbc:oracle:kprb:

    • jdbc:default:connection:

  • OracleDriverクラスのOracle固有のdefaultConnectionメソッドを使用します。

通常はdefaultConnectionの使用をお薦めします。

ノート:

サーバー側内部ドライバと接続するためにOracleDriverクラスを登録する必要はなくなりました。

OracleDriverクラスのdefaultConnectionメソッドによる接続

oracle.jdbc.OracleDriverクラスのdefaultConnectionメソッドは、Oracle拡張機能で、常に同じ接続オブジェクトを戻します。発生した接続オブジェクトを別の変数名に割り当て、このメソッドを複数回コールしたとしても、1つの接続オブジェクトのみが再利用されます。

defaultConnectionコールに接続文字列を含める必要はありません。次に例を示します。

import java.sql.*; 
import oracle.jdbc.*; 
  
class JDBCConnection 
{ 
  public static Connection connect() throws SQLException 
  { 
    Connection conn = null; 
    try {  
      // connect with the server-side internal driver
         conn = ora.defaultConnection(); 
      } 
 
    } catch (SQLException e) {...}
    return conn; 
  } 
}

この例にはconn.closeコールがないことに注意してください。JDBCコードがターゲット・サーバー内で実行されている場合、接続は暗黙的なデータ・チャネルで、クライアントからの場合のように明示的な接続インスタンスではありません。クローズしないでください。

OracleDriverは、デフォルトの接続インスタンスを格納するための静的な値です。接続が存在しクローズされていない場合に、メソッドOracleDriver.defaultConnectionはこのデフォルトの接続インスタンスを戻します。それ以外の場合、新しいオープン・インスタンスを作成し、静的な値に格納してコール元に戻します。

通常、OracleDriver.defaultConnectionメソッドを使用します。このメソッドは、高速でリソースをあまり使用しません。Javaストアド・プロシージャは注意深く記述する必要があります。たとえば、各コールを終了する前に文をクローズします。

通常、デフォルトの接続インスタンスはクローズしないでください。このインスタンスは複数の場所に格納される可能性がある単一インスタンスであり、クローズするとそれぞれの場所が使用できなくなります。クローズすると、それ以降にOracleDriver.defaultConnectionメソッドをコールしたときに、新しいオープン・インスタンスが作成されます。

OracleDataSource.getConnectionメソッドによる接続

ターゲット・サーバー内で実行中のコードから内部サーバー接続に接続するには、次のいずれかのURLとともに、OracleDataSource.getConnectionメソッドを使用できます。

OracleDataSource ods = new OracleDataSource();
ods.setURL("jdbc:oracle:kprb");
Connection conn = ods.getConnection();

または

OracleDataSource ods = new OracleDataSource();
ods.setURL("jdbc:default:connection");
Connection conn = ods.getConnection();

URL内で指定したユーザー名またはパスワードは、デフォルトのサーバー接続への接続では無視されます。

OracleDataSource.getConnectionメソッドをコールするたびに、このメソッドは新しいJava Connectionオブジェクトを戻します。オブジェクト・マップまたは型マップを操作している場合は、OracleDataSource.getConnectionをコールするたびに、このメソッドが新しい接続オブジェクトを戻すということに重要な意味があります。型マップは、特定のConnectionオブジェクトおよびそのオブジェクトの一部である状態に関連付けられます。プログラムの一部として複数の型マップを使用する場合は、getConnectionをコールして、各型マップに対して新しいConnectionオブジェクトを作成できます。

ノート:

OracleDataSource.getConnectionメソッドはコールするたびに新規オブジェクトを戻しますが、毎回、新しいデータベース接続を作成するわけではありません。同じ暗黙的なネイティブ接続を使用し、同じセッション状態(特にローカル・トランザクション)を共有します。

7.3 セッション・コンテキストおよびトランザクション・コンテキストについて

サーバー側ドライバは、デフォルト・セッションおよびデフォルト・トランザクションのコンテキストで動作します。デフォルト・セッションとは、JVMが起動されたセッションです。サーバー上では、事実上データベースにすでに接続されています。これは、デフォルト・セッションがないクライアント側とは異なります。クライアント側では、明示的にデータベースに接続する必要があります。

サーバーでは、自動コミット・モードは無効になっています。接続オブジェクトで適切なメソッドを使用して、明示的にトランザクションのCOMMITおよびROLLBACK操作を管理する必要があります。

conn.commit();

または

conn.rollback();

ノート:

ベスト・プラクティスとして、サーバー内ではトランザクションをコミットまたはロールバックしないことをお薦めします。

7.4 サーバー上でのJDBCのテスト

クライアント上で実行できるJDBCプログラムはほとんどすべてサーバー上でも実行できます。samplesディレクトリ内のすべてのプログラムは、少し修正するのみでサーバー上で実行できます。通常、修正は接続文に関するもののみです。

データベースへの接続を取得するための次のようなコード・フラグメントについて考えてみます。

ods.setUrl(
"jdbc:oracle:oci:@(DESCRIPTION=
  (ADDRESS=(PROTOCOL=TCP)(HOST=cluster_alias)
    (PORT=5221))
    (CONNECT_DATA=(SERVICE_NAME=orcl)))");
ods.setUser("HR");
ods.setPassword("hr");
Connection conn = ods.getConnection();  

サーバー側内部ドライバで使用できるように、このコード・フラグメントを変更できます。サーバー側内部ドライバでは、ユーザー、パスワードまたはデータベースの情報は不要です。接続文は次のように記述します。

ods.setUrl(
"jdbc:oracle:kprb:@");
Connection conn = ods.getConnection();  

ただし、接続を取得するには、次のようにOracleDriver.defaultConnectionメソッドをコールするのが最も便利な方法です。

Connection conn = OracleDriver.defaultConnection();  

7.5 サーバーへのアプリケーションのロード

サーバーにアプリケーションをロードする場合は、クライアントでコンパイル済の.classファイルをロードするか、.javaソース・ファイルをロードして、サーバーで自動的にコンパイルできます。

7.5.1 loadjavaユーティリティの使用

loadjavaユーティリティを使用してファイルをロードします。コマンドラインでソース・ファイル名を指定するか、Javaアーカイブ(JAR)ファイルにそのファイルを格納して、コマンドラインでそのJARファイル名を指定します。

実際のユーティリティを実行するloadjavaスクリプトは、Oracleホームのbinディレクトリにあります。このディレクトリは、Oracleをインストールすると自動的に作成されます。

ノート:

loadjavaユーティリティは圧縮ファイルをサポートしています。

サーバーへのクラス・ファイルのロード

アプリケーションに3つのクラス・ファイルFoo1.classFoo2.classおよびFoo3.classがある場合を考えてみます。各クラスは、サーバーで独自のクラス・スキーマ・オブジェクトに書き込まれます。

次のように、JDBC Oracle Call Interface(OCI)のデフォルト・ドライバを使用して、クラス・ファイルをロードできます。

  • クラス・ファイル名を個別に指定します。

    loadjava -user HR Foo1.class Foo2.class Foo3.class
    Password: password
    
  • ワイルドカードを使用してクラス・ファイル名を指定します。

    loadjava -user HR Foo*.class
    Password: password
    
  • クラス・ファイルが格納されているJARファイルを指定します。

    loadjava -user HR Foo.jar
    Password: password
    

次のように、JDBC Thinドライバを使用してファイルをロードできます。

loadjava -thin -user HR@localhost:5221:orcl Foo.jar
Password: password

ノート:

Oracle Database 12cリリース1 (12.1)以降、JDK 6およびJDK 7がサポートされています。ただし、ある時点でアクティブなJVMは1つのみです。

クラスは、サーバーのアクティブなランタイム・バージョンよりも新しいバージョンのJDKを使用してコンパイルされないようにしてください。

サーバーへのソース・ファイルのロード

.javaソース・ファイルをロードする際にloadjava -resolveオプションを有効にすると、サーバー側コンパイラはロード時にアプリケーションをコンパイルします。その結果、オリジナル・ソース・コードのソース・スキーマ・オブジェクトとコンパイル済出力の1つ以上のクラス・スキーマ・オブジェクトの両方が生成されます。

-resolveを指定しない場合は、ソースはコンパイルされずに、ソース・スキーマ・オブジェクトにロードされます。ただし、この場合は、ソースで定義されたクラスを最初に使用しようとしたときに、ソースが暗黙的にコンパイルされます。

たとえば、デフォルトのJDBC OCIドライバを使用して、Foo.javaをロードしてコンパイルするには、次のようにloadjavaを実行します。

loadjava -user HR -resolve Foo.java
Password: password

あるいは、次のコマンドを入力し、JDBC Thinドライバを使用してロードします。

loadjava -thin -user HR@localhost:5221:orcl -resolve Foo.java
Password: password

いずれの方法でも、ソース・スキーマ・オブジェクトに加えて、適切なクラス・スキーマ・オブジェクトが作成されます。

ノート:

通常はできるかぎりクライアントでソースをコンパイルし、ソース・ファイルではなく、.classファイルをサーバーにロードすることをお薦めします。

7.5.2 JVMコマンドラインの使用

JVMコマンドライン・オプションを使用してファイルをロードすることもできます。Oracle JVMへのコマンドライン・インタフェースは、JDKまたはJREのシェル・コマンドの使用方法と似ています。次のことが可能です。

  • 標準の-classpath構文を使用して、ロードするクラスの検索場所を示します。

  • 標準の-D構文を使用して、システム・プロパティを設定します。

このインタフェースは、文字列(VARCHAR2)引数を取り、この引数をコマンドライン入力として解析するPL/SQLファンクションです。形式が適切であれば、Oracle JVMで指定のJavaメソッドを実行します。これを実行するために、PL/SQLのパッケージDBMS_JAVAには次のファンクションが用意されています。

  • runjava

    runjavaファンクションを使用するには、次のようにします。

    FUNCTION runjava(cmdline VARCHAR2) RETURN VARCHAR2;
    
  • runjava_in_current_session

    runjava_in_current_sessionファンクションを使用するには、次のようにします。

    FUNCTION runjava_in_current_session(cmdline VARCHAR2) RETURN VARCHAR2;
    

ノート:

Oracle Database 11gリリース1以降には、Oracle JVM環境用のJust-In-Time(JIT)コンパイラがあります。Oracle JVMのJITコンパイラでは、以前のネイティブ・コンパイラと比較して高度な技術を使用し、動的に生成されたコードをコンパイルするため、実行速度が上がります。以前のネイティブ・コンパイラと異なり、JITコンパイラにはCコンパイラが必要ありません。プラグインのサポートがなくても有効です。