2 スタート・ガイド

この章では、Oracle Java Database Connectivity(JDBC)ドライバ・バージョン、データベース・バージョンおよびJava Development Kit(JDK)バージョン間の互換性について説明します。

また、クライアント・インストールと構成のテスト、および簡単なアプリケーションの実行方法の基本を説明します。この章の構成は、次のとおりです。

2.1 Oracle JDBCドライバのRDBMSおよびJDKバージョン互換性

Oracle Databaseリリース23cのJDBCドライバは、サポートされているすべてのOracle Databaseリリース(23c、21cおよび19c)で動作保証されています。

次の表に、JDBCとOracle Databaseの相互運用性マトリックスまたは動作保証マトリックスを示します。

JDBCドライバのバージョン Database 23.x Database 21.x Database 19.x
JDBC 23 あり あり あり
JDBC 21.x あり あり あり
JDBC 19.x あり あり あり

Oracle JDBCドライバは常に、新しいリリースごとに最新のJDKバージョンに準拠しています。一部のバージョンでは、JDBCドライバは複数のJDKバージョンをサポートしています。次の表に、リリース固有のJDBC JARファイルと、様々なOracle DatabaseバージョンでサポートされているJDKバージョンを示します。

ノート:

ojdbc8.jarはJDBC 4.3 APIをサポートしていないため、JDK 11、JDK 17およびJDK 19でのojdbc8.jarサポートはJDBC 4.2 APIのみに制限されます。
Oracle JDBCバージョン リリース固有のJDBC JARファイルとサポートされているJDKバージョン
23.x ojdbc11.jarとJDK 11、JDK 17、JDK 19およびJDK 21

ojdbc8.jar、およびJDK 8とJDK 11

21.x ojdbc11.jarとJDK 11、JDK 17およびJDK 19

ojdbc8.jar、およびJDK 8とJDK 11

19.x ojdbc10.jar、およびJDK 11とJDK 17

ojdbc8.jarとJDK 8、JDK 11、JDK 17およびJDK 19

2.2 JDBCクライアント・インストールの検証

この項では、JDBCクライアントのインストールを検証するために実行する必要があるステップについて説明します。

ノート:

  • JDBC Thinドライバを使用する場合は、クライアント・コンピュータにその他のインストールは必要ありません。JDBC Oracle Call Interface(OCI)ドライバを使用する場合は、Oracleクライアント・ソフトウェアもインストールする必要があります。これには、Oracle NetおよびOCIライブラリが含まれます。
  • JDBC Thinドライバでは、データベースがインストールされているコンピュータ上にTCP/IPリスナーが必要です。

この項では、選択したドライバのインストールが完了しているものとして、JDBCドライバのOracleクライアントのインストールを検証するステップを説明します。Oracle JDBCドライバのインストールは、プラットフォームによって異なります。プラットフォーム固有の情報が記載されたマニュアルの、ドライバのインストール手順に従う必要があります。

2.2.1 環境変数のチェック

この項では、主にSolaris、LinuxおよびMicrosoft Windowsプラットフォームに関して、JDBC OCIドライバとJDBC Thinドライバのために設定する必要がある環境変数について説明します。

JDBC Thinドライバ

JDBC Thinドライバを使用するには、CLASSPATH環境変数を設定する必要があります。CLASSPATH環境変数には次のものを含めます。

jdbc/lib/ojdbc11.jar
jlib/orai18n.jar

ノート:

JTA機能およびJNDI機能を使用する場合は、jta.jarjndi.jarCLASSPATH環境変数に指定する必要があります。

JDBC OCIドライバ

JDBC OCIドライバを使用するには、CLASSPATH環境変数を設定する必要があります。CLASSPATH環境変数には次のものを含めます。

ORACLE_HOME/jdbc/lib/ojdbc11.jar
ORACLE_HOME/jlib/orai18n.jar

ノート:

JTA機能およびJNDI機能を使用する場合は、jta.jarjndi.jarCLASSPATH環境変数に指定する必要があります。

JDBC OCIドライバを使用するには、ライブラリ・パス環境変数に次の値を設定する必要もあります。

  • SolarisまたはLinuxの場合は、LD_LIBRARY_PATH環境変数を次のように設定します。

    ORACLE_HOME/lib
    

    このディレクトリには、libocijdbc11.so共有オブジェクト・ライブラリが格納されます。

  • Microsoft Windowsでは、次のようにPATH環境変数を設定します。

    ORACLE_HOME\bin
    

    このディレクトリには、ocijdbc11.dll動的リンク・ライブラリが格納されます。

ライブラリ・パス環境変数にJDBC OCI Instant Clientデータ共有ライブラリを指定すると、すべてのJDBC OCIデモ用プログラムをInstant Clientモードで実行できます。

サーバー側Thinドライバの許可の設定

JDBCサーバー側のThinドライバでデータベースへのその接続のためにソケットが開かれることから、JDBCサーバー側のThinドライバを使用するには、権限を設定する必要があります。そのため、Oracle DatabaseによってJavaセキュリティ・モデルが強制適用され、SocketPermissionオブジェクトのチェックが実行されます。

次の例は、ユーザーHRに許可を付与する方法を示しています。

CREATE ROLE jdbcthin;
CALL dbms_java.grant_permission('JDBCTHIN', 'java.net.SocketPermission', '*', 'connect');
GRANT jdbcthin TO HR;

grant_permissionコールのJDBCTHINは大文字で指定する必要があることに注意してください。アスタリスク(*)はパターンです。特定のコンピュータまたはポートのみに接続する許可を付与してユーザーへの許可を制限できます。

2.2.2 Javaコードのコンパイルと実行の確認

Javaがクライアント・システムで正しく設定されたことを確認するには、ORACLE_HOME/jdbc/demoの下のsamplesディレクトリに移動します。次に、コマンドラインで次のコマンドを順に入力して、JavaコンパイラおよびJavaインタプリタがエラーなく実行されていることを確認します。

javac

java

これらの各コマンドは、オプションとパラメータのリストを表示して終了します。可能であれば、jdbc/demo/samples/generic/SelectExampleなどの簡単なテスト・プログラムを使用して、コンパイルと実行の確認をしてください。

2.2.3 JDBCドライバのバージョンの確認

アプリケーションで正しいバージョンのJDBCドライバを使用することが非常に重要です。

JDBCドライバのバージョンを確認するには、次のコマンドを使用します:

  • java -jar ojdbc8.jar

  • java -jar ojdbc11.jar

次のサンプル・コードで示すように、OracleDatabaseMetaDataクラスのgetDriverVersionメソッドをコールすることもできます。

import java.sql.*;
import oracle.jdbc.*;
import oracle.jdbc.pool.OracleDataSource;

class JDBCVersion
{
  public static void main (String args[]) throws SQLException
  {
    OracleDataSource ods = new OracleDataSource();
    ods.setURL("jdbc:oracle:thin:HR/<password>@<host>:<port>:<service>");
    Connection conn = ods.getConnection();

    // Create Oracle DatabaseMetaData object
    DatabaseMetaData meta = conn.getMetaData();

    // gets driver info:
    System.out.println("JDBC driver version is " + meta.getDriverVersion());
  }
}

2.2.4 JDBCおよびデータベース接続のテスト

samplesディレクトリには、特定のOracle JDBCドライバ用のサンプル・プログラムが格納されています。その1つであるJdbcCheckup.javaは、JDBCおよびデータベース接続のテスト用です。このプログラムには、ユーザー名、パスワードおよび接続するデータベース名の入力が必要です。このプログラムは、データベースに接続し、「Hello World」という文字列の問合せを行い、それを画面に出力します。

samplesディレクトリでJdbcCheckup.javaプログラムをコンパイルして実行します。問合せの結果の画面出力でエラーが発生しなければ、JavaおよびJDBCは正しくインストールされています。

JdbcCheckup.javaは簡単なプログラムですが、次の操作を実行することにより、いくつかの重要な機能を示します。

  • JDBCクラスを含む、必要なJavaクラスのインポート

  • DataSourceインスタンスの作成

  • データベースへの接続

  • 単純な問合せの実行

  • 問合せ結果の画面への出力

JDBC OCIドライバを使用するJdbcCheckup.javaプログラムは次のとおりです。

/*
 * This sample can be used to check the JDBC installation.
 * Just run it and provide the connect information. It will select
 * "Hello World" from the database.
 */

// You need to import the java.sql and JDBC packages to use JDBC
import java.sql.*;
import oracle.jdbc.*;
import oracle.jdbc.pool.OracleDataSource;

// We import java.io to be able to read from the command line
import java.io.*;

class JdbcCheckup
{
  public static void main(String args[]) throws SQLException, IOException
  {

    // Prompt the user for connect information
    System.out.println("Please enter information to test connection to 
                          the database");
    String user;
    String password;
    String database;

    user = readEntry("user: ");
    int slash_index = user.indexOf('/');
    if (slash_index != -1)
    {
      password = user.substring(slash_index + 1);
      user = user.substring(0, slash_index);
    }
    else
      password = readEntry("password: ");
    database = readEntry("database(a TNSNAME entry): ");

    System.out.print("Connecting to the database...");
    System.out.flush();
    System.out.println("Connecting...");
    // Open an OracleDataSource and get a connection
    OracleDataSource ods = new OracleDataSource();
    ods.setURL("jdbc:oracle:oci:@" + database);
    ods.setUser(user);
    ods.setPassword(password);
    Connection conn = ods.getConnection();
    System.out.println("connected.");

    // Create a statement
    Statement stmt = conn.createStatement();

    // Do the SQL "Hello World" thing
    ResultSet rset = stmt.executeQuery("select 'Hello World' from dual");

    while (rset.next())
      System.out.println(rset.getString(1));
    // close the result set, the statement and the connection
    rset.close();
    stmt.close();
    conn.close();
    System.out.println("Your JDBC installation is correct.");
  }

  // Utility function to read a line from standard input
  static String readEntry(String prompt)
  {
    try
    {
      StringBuffer buffer = new StringBuffer();
      System.out.print(prompt);
      System.out.flush();
      int c = System.in.read();
      while (c != '\n' && c != -1)
      {
        buffer.append((char)c);
        c = System.in.read();
      }
      return buffer.toString().trim();
    }
    catch(IOException e)
    {
      return "";
    }
  }
}

2.3 JDBCでの基本ステップ

JDBCクライアント・インストールの検証が完了すると、JDBCアプリケーションの作成を開始できます。Oracle JDBCドライバを使用する場合は、プログラムに特定のドライバ固有情報を含める必要があります。この項では、ドライバ固有情報の追加場所と追加方法について、チュートリアルの形式で説明します。チュートリアルは、クライアントからデータベースへの接続および問合せを行うコードを作成する方法を、ステップを追って説明します。

次のタスクを実行するコードを記述する必要があります。

  1. パッケージのインポート
  2. データベースへの接続のオープン
  3. 文オブジェクトの作成
  4. 問合せの実行と結果セット・オブジェクトの取出し
  5. 結果セット・オブジェクトの処理
  6. 結果セット・オブジェクトとStatementオブジェクトのクローズ
  7. データベースの変更
  8. 変更のコミットについて
  9. 接続のクローズ

ノート:

最初の3つのタスク用のOracleドライバ固有情報を指定して、プログラムがJDBC Application Program Interface(API)を使用してデータベースにアクセスできるようにします。その他のタスクについては、Javaアプリケーションの場合と同様に、標準JDBC Javaコードを使用できます。

2.3.1 パッケージのインポート

使用するOracle JDBCドライバの種類にかかわらず、次の構文を使用して、表2-1に示されているimport文をプログラムの最初に記述する必要があります。

import <package_name>;

表2-1 JDBCドライバ用のimport文

import文 提供パッケージ

import java.sql.*;

標準のJDBCパッケージ。

import java.math.*;

BigDecimalクラスおよびBigIntegerクラス。アプリケーションでこれらのクラスを使用しない場合は、このパッケージを省略できます。

import oracle.jdbc.*;

import oracle.jdbc.pool.*;

import oracle.sql.*;

JDBCに対するOracleの拡張機能。これはオプションです。

OracleDataSource

Oracle型拡張機能。これはオプションです。

オプションとなっているOracleパッケージは、Oracle JDBCドライバの拡張機能へのアクセスを提供しますが、この項の例には必要ありません。

ノート:

ワイルド・カードのアスタリスク(*)は使用せずに、アプリケーションに必要なクラスのみをインポートすることをお薦めします。このガイドでは簡単にするためにアスタリスク(*)を使用していますが、クラスおよびインタフェースのインポート方法としてはお薦めしません。

2.3.2 データベースへの接続のオープン

最初に、OracleDataSourceインスタンスを作成する必要があります。次に、OracleDataSource.getConnectionメソッドを使用してデータベースへの接続をオープンします。取り出した接続のプロパティは、OracleDataSourceインスタンスから導出されたものです。URL接続プロパティを設定した場合は、TNSEntryNameDatabaseNameServiceNameServerNamePortNumberNetwork Protocolおよびドライバのタイプを含む他のプロパティはすべて無視されます。

データベースURL、ユーザー名およびパスワードの指定

次のコードは、データソースのURL、ユーザー名およびパスワードを設定します。

OracleDataSource ods = new OracleDataSource();
ods.setURL(url);
ods.setUser(user);
ods.setPassword(password);

次の例では、JDBC Thinドライバを使用して、パスワードがhrのユーザーHRを、サービス名がorclのデータベースに、ホストmyhostのポート5221経由で接続します。

OracleDataSource ods = new OracleDataSource();
String url = "jdbc:oracle:thin:@myhost:5221/orcl";
ods.setURL(url);
ods.setUser("HR");
ods.setPassword("hr");
Connection conn = ods.getConnection();

ノート:

引数で指定されたユーザー名とパスワードは、URLで指定されたユーザー名とパスワードをオーバーライドします。

ユーザー名とパスワードを含むデータベースURLの指定

次の例では、JDBC Oracle Call Interface(OCI)ドライバを使用して、パスワードがhrのユーザーHRを、Transparent Network Substrate(TNS)エントリがmyTNSEntryであるデータベース・ホストに接続します。この場合、URLは、ユーザー名とパスワードを含む、唯一の入力パラメータです。

String url = "jdbc:oracle:oci:HR/<password>@myTNSEntry");
ods.setURL(url);
Connection conn = ods.getConnection();

Thinドライバを使用して接続する場合は、ポート番号を指定する必要があります。たとえば、ポート5221上にTCP/IPリスナーを持つホストmyhost上のデータベースに接続し、サービス識別子がorclである場合は、次のようなコードを記述します。

String URL = "jdbc:oracle:thin:HR/<password>@myhost:5221/orcl");
ods.setURL(URL);
Connection conn = ods.getConnection();

2.3.3 文オブジェクトの作成

データベースに接続し、そのプロセスでConnectionオブジェクトを作成したら、次のステップは、Statementオブジェクトを作成します。JDBC ConnectionオブジェクトのcreateStatementメソッドは、JDBC Statement型のオブジェクトを返します。前の項の、Connectionオブジェクトconnが作成された例の続きとして、Statementオブジェクトを作成する方法の例を示します。

Statement stmt = conn.createStatement();

2.3.4 問合せの実行と結果セット・オブジェクトの取出し

データベースへの問合せを行う場合、StatementオブジェクトのexecuteQueryメソッドを使用します。このメソッドは、入力としてSQL文を受け取り、JDBC ResultSetオブジェクトを戻します。

ノート:

  • Statementオブジェクトを実行するために使用されるメソッドは、実行されているSQL文の種類により異なります。StatementオブジェクトがResultSetオブジェクトを戻すSQL問合せを表している場合は、executeQueryメソッドを使用します。SQLが更新件数を戻すDDL文またはDML文の場合は、executeUpdateメソッドを使用します。SQL文の種類がわからない場合は、executeメソッドを使用します。

  • 標準JDBCドライバの場合、実行されているSQL文字列がResultSetオブジェクトを戻さないと、executeQueryメソッドでSQLException例外がスローされます。Oracle JDBCドライバの場合、実行されているSQL文字列がResultSetオブジェクトを戻さなくても、executeQueryメソッドでSQLException例外はスローされません。

この例を続けるには、Statementオブジェクトstmtを作成したら、次のステップは、問合せを実行し、EMPLOYEESという従業員の表のfirst_name列の内容が含まれたResultSetオブジェクトを戻すことです。

ResultSet rset = stmt.executeQuery ("SELECT first_name FROM employees");

2.3.5 結果セット・オブジェクトの処理

問合せの実行後は、ResultSetオブジェクトのnext()メソッドを使用して結果を反復します。このメソッドは、結果セットを行ごとに進み、結果セットの最後に達するとそれを検出します。

結果セット内を反復しながらデータを引き出すには、ResultSetオブジェクトの適切なgetXXXメソッドを使用します。このXXXには、Javaのデータ型が対応します。

たとえば、次のコードは、以前の項のResultSetオブジェクトrset内を反復して、各従業員名の取出しおよび出力を行います。

while (rset.next())
   System.out.println (rset.getString(1));

next()メソッドは、結果セットの最後に達するとfalseを戻します。従業員名は、Java String値として実体化されます。

2.3.6 結果セット・オブジェクトとStatementオブジェクトのクローズ

ResultSetStatementオブジェクトの使用後に、明示的にこれらをクローズする必要があります。これは、Oracle JDBCドライバの使用時に作成した、すべてのResultSetおよびStatementオブジェクトに適用されます。ドライバには、ファイナライザ・メソッドがありません。クリーン・アップ・ルーチンは、ResultSetおよびStatementクラスのcloseメソッドで実行されます。明示的にResultSetおよびStatementオブジェクトをクローズしないと、深刻なメモリー・リークが発生する場合があります。また、データベースのカーソルが不足します。結果セットと文の両方をクローズすると、データベース内の対応するカーソルが解放されます。結果セットのみをクローズすると、カーソルは解放されません。

たとえば、ResultSetオブジェクトがrsetで、Statementオブジェクトがstmtの場合は、次のコードの行を使用して結果セットと文をクローズできます。

rset.close();
stmt.close();

指定したConnectionオブジェクトが作成するStatementオブジェクトをクローズする場合、接続自体はオープンしたままになります。

ノート:

一般に、close文はfinally句に書き込みます。

2.3.7 データベースの変更

DML操作

INSERT操作またはUPDATE操作などのDML(データ操作言語)操作を実行するには、StatementオブジェクトまたはPreparedStatementオブジェクトのいずれかを作成します。PreparedStatementオブジェクトによって、様々な入力パラメータのセットで文を実行できます。JDBC ConnectionオブジェクトのprepareStatementメソッドを使用すると、様々なバインド・パラメータを取り、文定義でJDBC PreparedStatementオブジェクトを戻す文を定義できます。

データベースに送信するプリペアド文にデータをバインドするには、PreparedStatementsetXXXメソッドを使用します。

次の例では、プリペアド文を使用して、EMPLOYEES表に2行を追加するINSERT操作を実行する方法を示します。

    // Prepare to insert new names in the EMPLOYEES table
PreparedStatement pstmt = null;
try{
    pstmt = conn.prepareStatement ("insert into EMPLOYEES (EMPLOYEE_ID, FIRST_NAME) values (?, ?)");

    // Add LESLIE as employee number 1500
    pstmt.setInt (1, 1500);          // The first ? is for EMPLOYEE_ID
    pstmt.setString (2, "LESLIE");   // The second ? is for FIRST_NAME
    // Do the insertion
    pstmt.execute();

    // Add MARSHA as employee number 507
    pstmt.setInt (1, 507);           // The first ? is for EMPLOYEE_ID
    pstmt.setString (2, "MARSHA");   // The second ? is for FIRST_NAME
    // Do the insertion
    pstmt.execute();
}

finally{
		if(pstmt!=null)

    // Close the statement
    pstmt.close();
}

DDL操作

データ定義言語(DDL)操作を実行するには、Statementオブジェクトを作成する必要があります。次の例では、データベースに表を作成する方法を示します。

//create table EMPLOYEES with columns EMPLOYEE_ID and FIRST_NAME
String query;
Statement stmt=null;

try{
    query="create table EMPLOYEES " +
          "(EMPLOYEE_ID int, " +
          "FIRST_NAME varchar(50))";
    stmt = conn.createStatement();
    stmt.executeUpdate(query);
    }
finally{
     //close the Statement object
     stmt.close();
    }

ノート:

PreparedStatementオブジェクトを使用してDDL操作を実行することもできます。ただし、PreparedStatementオブジェクトの便利なところはパラメータを設定できることですが、DDL操作にはパラメータがないため、このオブジェクトを使用しないでください。

また、データベース制限のため、PreparedStatementオブジェクトをDDL操作に使用した場合、動作するのは初回実行時のみです。そのため、DDL操作にはStatementオブジェクトのみを使用してください。

次の例では、再実行の前にDDL文を準備する方法を示しています。

//
Statement stmt = null;
PreparedStatement pstmt = null;
try{
    pstmt = conn.prepareStatement ("insert into EMPLOYEES (EMPLOYEE_ID, FIRST_NAME) values (?, ?)");
    stmt = conn.createStatement("truncate table EMPLOYEES"); 
 
    // Add LESLIE as employee number 1500
    pstmt.setInt (1, 1500);          // The first ? is for EMPLOYEE_ID
    pstmt.setString (2, "LESLIE");   // The second ? is for FIRST_NAME
    pstmt.execute();
    stmt.executeUpdate();
 
    // Add MARSHA as employee number 507
    pstmt.setInt (1, 507);           // The first ? is for EMPLOYEE_ID
    pstmt.setString (2, "MARSHA");   // The second ? is for FIRST_NAME
    pstmt.execute();
    stmt.executeUpdate();
    }
finally{
if(pstmt!=null)
 
    // Close the statement
     pstmt.close();
}

2.3.8 変更のコミットについて

デフォルトでは、データ操作言語(DML)操作は実行時に自動的にコミットされます。これは自動コミット・モードともいいます。自動コミット・モードがオンで、接続オブジェクトのcommitまたはrollbackメソッドを使用して、COMMITまたはROLLBACK操作を実行する場合、次のエラー・メッセージを受信します。

表2-2 自動コミット・モードがオンの場合に実行された操作に対するエラー・メッセージ

操作 エラー・メッセージ

COMMIT

自動コミットがオンの状態でコミットできませんでした。

ROLLBACK

自動コミットがオンの状態でロールバックできませんでした。

COMMITまたはROLLBACK操作を実行し、前の表に示したエラー・メッセージを受信したときにSQLExceptionが発生した場合、接続の自動コミット・ステータスを確認します。これは、自動コミット値がtrueに設定されている接続でこれらの操作を実行した場合、例外が発生するためです。

このような例外は、次の場合のいずれかで発生します。

  • 自動コミット・ステータスがtrueに設定されていて、commitまたはrollbackメソッドがコールされた場合

  • 自動コミットのデフォルトのステータスが変更されないで、commitまたはrollbackメソッドがコールされた場合

  • COMMIT_ON_ACCEPT_CHANGESプロパティの値がtrueで、acceptChangesメソッドが行セットでコールされた後にcommitまたはrollbackメソッドがコールされた場合

ただし、Connectionオブジェクトでの次のメソッドのコールによって、自動コミット・モードを無効にできます。

conn.setAutoCommit(false);

自動コミット・モードを無効にした場合は、Connectionオブジェクトで適切なメソッドをコールして、変更を手動でコミットするか、ロールバックする必要があります。

conn.commit();

または

conn.rollback();

COMMIT操作またはROLLBACK操作は、直前のCOMMITまたはROLLBACK以降に実行されたすべてのDML文に影響を与えます。

ノート:

  • 自動コミット・モードを無効にして、直前の変更を明示的にコミットまたはロールバックせずに接続をクローズした場合は、暗黙的なCOMMIT操作が実行されます。

  • すべてのデータ定義言語(DDL)操作には、常に暗黙的なCOMMITが含まれます。自動コミット・モードを無効にした場合、この暗黙的なCOMMITは、まだ明示的にコミットまたはロールバックされていない保留DML文もコミットします。

2.3.8.1 コミット動作の変更

トランザクションによりデータベースを更新すると、この更新に対応するREDOエントリが生成されます。Oracle Databaseでは、トランザクションの完了まで、このREDOを一時的にメモリーに保存します。トランザクションをコミットすると、ログ・ライター(LGWR)プロセスによりコミットのREDOエントリが、そのトランザクションにおけるすべての変更について累積したREDOエントリとともに、ディスクに書き込まれます。デフォルトでは、Oracle Databaseは、コールがクライアントに戻る前にREDOをディスクに書き込みます。アプリケーションはREDOエントリがディスクに保存されるまで待つ必要があるため、この動作によりコミットに待機時間が生じます。

アプリケーションに非常に高いトランザクション・スループットが必要で、コミット待機時間を短縮するためにコミットの永続性を犠牲にしてもよいという場合は、アプリケーションの必要に応じて、デフォルトのCOMMIT操作の動作を変更できます。COMMIT操作の動作は、次のオプションにより変更できます。

  • WAIT

  • NOWAIT

  • WRITEBATCH

  • WRITEIMMED

これらのオプションを指定すると、コミット段階の2つの異なる面を制御できます。

  • COMMITコールが、サーバーによって処理されるまで待機するかどうか。これには、WAITオプションまたはNOWAITオプションを使用します。

  • ログ・ライターがコールをバッチ処理するかどうか。これには、WRITEIMMEDオプションまたはWRITEBATCHオプションを使用します。

異なるオプションを組み合せることもできます。たとえば、COMMITコールがサーバーによる処理を待たずに戻り、ログ・ライターがコミットをバッチ処理するようにするには、NOWAITオプションとWRITEBATCHオプションを一緒に使用します。たとえば:

((OracleConnection)conn).commit(
    EnumSet.of(
      OracleConnection.CommitOption.WRITEBATCH,
      OracleConnection.CommitOption.NOWAIT));

ノート:

WAITオプションとNOWAITオプションは、逆の意味を持つため、一緒に使用できません。一緒に使用すると、JDBCドライバは例外をスローします。同じことが、WRITEIMMEDオプションとWRITEBATCHオプションにも当てはまります。

2.3.9 接続のクローズ

必要な操作をすべて実行し、接続が不要になった後に、データベースへの接続をクローズする必要があります。次のように、Connectionオブジェクトのcloseメソッドを使用してクローズできます。

conn.close();

ノート:

一般に、close文はfinally句に書き込みます。

2.4 サンプル: 接続、問合せおよび結果処理

次の例は、前の項で説明した処理を例証するものです。Oracle JDBC Thinドライバを使用してデータソースを作成し、データベースに接続し、Statementオブジェクトを作成して問合せを実行し、結果セットを処理します。

Statementオブジェクトの作成、問合せの実行、ResultSetの戻りと処理、および文と接続のクローズを行うコードは、標準JDBC APIを使用していることに注意してください。

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.SQLException;
import oracle.jdbc.pool.OracleDataSource;

class JdbcTest
{
   public static void main (String args []) throws SQLException
   {

OracleDataSource ods = null;
Connection conn = null;
Statement stmt = null;
ResultSet rset = null;

      // Create DataSource and connect to the local database
      ods = new OracleDataSource();
      ods.setURL("jdbc:oracle:thin:@localhost:5221/orcl");
      ods.setUser("HR");
      ods.setPassword("hr");
      conn = ods.getConnection();

try
{
      // Query the employee names 
      stmt = conn.createStatement (); 
      rset = stmt.executeQuery ("SELECT first_name FROM employees");

      // Print the name out 
      while (rset.next ())
         System.out.println (rset.getString (1));
    }

      //Close the result set, statement, and the connection

finally{
      if(rset!=null) rset.close();
      if(stmt!=null) stmt.close();
      if(conn!=null) conn.close();
}
   } 
} 

OCIドライバ用のコードを利用する場合は、OracleDataSource.setURLメソッドのコールを次の文で置き換えます。

ods.setURL("jdbc:oracle:oci:@MyHostString");

MyHostStringには、TNSNAMES.ORAファイル内のエントリを指定します。

2.5 注釈のサポート

注釈は、開発者がデータベース・スキーマ・オブジェクトの使用状況プロパティを一元的に登録するための軽量な宣言機能です。

新しいオブジェクトを(CREATE文を使用して)作成したり、既存のオブジェクトを(ALTER文を使用して)変更するときに、注釈をスキーマ・オブジェクトに追加できます。個々の注釈には名前とオプションの値があり、どちらも自由形式のテキスト・フィールドです。スキーマ・オブジェクトには複数の注釈を指定できます。

Oracle Databaseリリース23c以降、JDBCドライバは注釈をサポートしています。次のメソッドを使用して、注釈を操作できます。

oracle.jdbc.AdditionalDatabaseMetaData.getAnnotations​(java.lang.String objectName, java.lang.String domainName, 
java.lang.String domainOwner) throws java.sql.SQLException
oracle.jdbc.OracleResultSetMetaData.getAnnotations​(java.lang.String objectName, java.lang.String columnName, 
java.lang.String domainName, java.lang.String domainOwner) throws java.sql.SQLException

これらのメソッドは、指定された表またはビューに関連付けられた注釈を返します。 指定されたオブジェクトに使用できる注釈がない場合は、nullを返します。

2.6 Oracle True Cacheのサポート

Oracle True Cacheは、Oracle Database用の、一貫性が確保され自動管理される、メモリー内のキャッシュです。バッファ・キャッシュのデータのみを使用して問合せに対応します。

ノート:

この機能は、Oracle Database 23c Beta 3プログラムに参加するユーザーのみが使用できます。

True Cacheはプライマリ・データベースの完全に機能する読取り専用レプリケーションであり、大部分がディスクレスです。これは、アプリケーションが最新データをほとんど必要としないという事実を利用し、かわりにキャッシュされたデータを使用できます。キャッシュされたデータを使用する問合せは、中間層にあるTrue Cacheインスタンスに対して発行できます。そのため、アプリケーションは2つのデータ・ソースを維持する必要があり、1つはプライマリ・データベース、もう1つはTrue Cacheインスタンスに対するものとなります。

構成すると、JDBCドライバはTrue Cacheインスタンスとプライマリ・データベースの両方で問合せを実行できます。アプリケーションは、プライマリ・データベースとTrue Cacheインスタンスの両方を認識する1つの論理接続のみを保持します。問合せは、JDBCドライバの論理接続が読取り専用モードの場合はTrue Cacheインスタンスで実行され、そうでない場合はプライマリ・データベースで問合せが実行されます。これにより、プライマリ・データベースに送信される問合せの数が減るため、スケーラビリティが向上し、アプリケーションの応答時間が短縮されます。

True Cache機能を有効にするには、新しいoracle.jdbc.useTrueCacheDriverConnectionプロパティの値をtrueに設定する必要があります。True Cache機能を有効にすると、JDBCドライバは標準のjava.sql.Connection.setReadOnly(boolean)およびjava.sql.Connection.isReadOnly()メソッドを使用して、接続を読取り専用としてマークします。デフォルトでは、接続の読取り専用モードはfalseです。

次のコード・スニペットは、True Cache機能の使用方法を示しています。

...
OracleDataSource ods = new oracle.jdbc.pool.OracleDataSource();
ods.setURL(DB_URL);
ods.setUser(DB_USER);
ods.setPassword(DB_PASSWORD);
Properties props = new Properties();
props.setProperty("oracle.jdbc.useTrueCacheDriverConnection", "true");
ods.setConnectionProperties(props);
// this is a True Cache driver connection and it can be used to execute 
// queries on both the primary database and a True Cache instance
Connection conn = ods.getConnection();
Statement stmt = conn.createStatement();
// Default value of connection read-only flag is false which means
// the SQL_QUERY1 is executed on the primary database 
ResultSet rs = stmt.executeQuery(SQL_QUERY1);
// set the read-only flag to true, in order to execute SQL_QUERY2 
// on a True Cache instance
conn.setReadOnly(true);
ResultSet rs1 = stmt.executeQuery(SQL_QUERY2);
...

2.7 Bequeathプロトコルのサポート

Oracle Databaseリリース23c以降、JDBC Thinドライバでは、Linuxプラットフォームで実行されているアプリケーションに対してBequeathプロトコル(BEQ)をサポートしています。

Bequeathプロトコルを使用してデータベースに接続するには、ドライバがOracleサーバー・プロセスの実行可能ファイルを特定できるように、ORACLE_HOME変数の値を設定する必要があります。通常、ORACLE_HOME変数は、データベースのインストール場所(/var/lib/oracle/dbhome)を指します。次の2つの方法で場所をリセットできます。

  • 接続URL内
  • 現在のアプリケーションの環境内

有効にする必要がある2番目の必須変数は、ORACLE_SIDです。ORACLE_HOME変数の設定と同様に、接続URLまたは現在のアプリケーション環境でORACLE_SIDを設定できます。Bequeath接続を確立するには、BEQプロトコルを有効にする必要があります。これは、認証サービス・プロパティのデフォルト設定です。

次の例は、接続URLでORACLE_HOME変数およびORACLE_SIDを設定する方法を示しています。

jdbc:oracle:thin:@(DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq))
(ENVS=ORACLE_HOME=/var/lib/oracle/dbhome,ORACLE_SID=oraclesid))

2.8 非表示列のサポート

今回のリリース以降、Oracle Databaseでは非表示の列をサポートしています。この機能を使用すると、非表示モードで表に列を追加し、後で表示するようにできます。JDBCでは、非表示列の情報を取得するAPIを提供しています。列が非表示かどうかについての情報を取得するには、次のようにoracle.jdbc.OracleResultSetMetaDataインタフェースで利用可能なisColumnInvisibleメソッドを使用できます。

...
Connection conn = DriverManager.getConnection(jdbcURL, user, password);
Statement stmt = conn.createStatement ();
stmt.executeQuery ("create table hiddenColsTable (a varchar(20), b int invisible)");
stmt.executeUpdate("insert into hiddenColsTable (a,b ) values('somedata',1)");
stmt.executeUpdate("insert into hiddenColsTable (a,b) values('newdata',2)");
 
System.out.println ("Invisible columns information");
try 
{
      ResultSet rset = stmt.executeQuery("SELECT a, b FROM hiddenColsTable");
      OracleResultSetMetaData rsmd = (OracleResultSetMetaData)rset.getMetaData();
      while (rset.next())
      {
        System.out.println("column1 value:" + rset.getString(1));
        System.out.println("Visibility:" + rsmd.isColumnInvisible(1));
        System.out.println("column2 value:" + rset.getInt(2));
        System.out.println("Visibility:" + rsmd.isColumnInvisible(2));
      }
}
catch (Exception ex)
{
       System.out.println("Exception :" + ex);
       ex.printStackTrace();
}

また、oracle.jdbc.OracleDatabaseMetaDataクラスで利用可能なgetColumnsメソッドを使用して、非表示列の情報を取得することもできます。

...
Connection conn = DriverManager.getConnection(jdbcURL, user, password);
Statement stmt = conn.createStatement ();
stmt.executeQuery ("create table hiddenColsTable (a varchar(20), b int invisible)");
stmt.executeUpdate("insert into hiddenColsTable (a,b ) values('somedata',1)");
stmt.executeUpdate("insert into hiddenColsTable (a,b) values('newdata',2)");
 
 System.out.println ("getColumns for table with invisible columns");
 try
 {
      DatabaseMetaData dbmd = conn.getMetaData();
      ResultSet rs = dbmd.getColumns(null, "HR", "hiddenColsTable", null);
      OracleResultSetMetaData rsmd = (OracleResultSetMetaData)rs.getMetaData();
      int colCount = rsmd.getColumnCount();
      System.out.println("colCount: " + colCount);
      String[] columnNames = new String [colCount];
 
      for (int i = 0; i < colCount; ++i)
      {
        columnNames[i] = rsmd.getColumnName (i + 1);
      }
 
      while (rs.next())
      {
        for (int i = 0; i < colCount; ++i)
           System.out.println(columnNames[i] +":" +rs.getString (columnNames[i]));
      }
 }
 catch (Exception ex)
 {
      System.out.println("Exception: " + ex);
      ex.printStackTrace();
 }

ノート:

サーバー側の内部ドライバであるkprbは、非表示列の情報のフェッチをサポートしていません。

2.9 JSONデータの検証のサポート

Oracle Databaseリリース18c以降、JDBCドライバは、ResultSetで返される列がJSON列であるかどうかを確認できます。列がJSONであるかどうかについての情報を取得するには、次のようにoracle.jdbc.OracleResultSetMetaDataインタフェースで利用可能なisColumnJSONメソッドを使用できます。

例2-1 例


  ...
  public void test(Connection conn)
      throws Exception{

    try {
      show ("tkpjb26776242 - start");
      createTable(conn);    
      
      String sql = "SELECT col1, col2, col3, col4, col5, col6, col7, col8 FROM tkpjb26776242_tab";
      Statement stmt = conn.createStatement();
      ResultSet rs = stmt.executeQuery(sql);
      ResultSetMetaData rsmd = rs.getMetaData();

      OracleResultSetMetaData orsmd   = (OracleResultSetMetaData)rsmd;
              
      int colCnt = orsmd.getColumnCount();
      show("Table has " + colCnt + " columns.");
      for (int i = 1; i <= colCnt; i++) {
        String columnName = orsmd.getColumnName(i);
        String typeName = orsmd.getColumnTypeName(i);
        boolean invisible = orsmd.isColumnInvisible(i);
        boolean json = orsmd.isColumnJSON(i);
        show(columnName + "  " + typeName + (invisible?"   INVISIBLE":"") + (json?"   JSON":""));
      }

      rs.close();
      stmt.close();
      
      show ("tkpjb26776242 - end");
    }
    finally {
      dropTable(conn);
    }
  }
  
  
  private void createTable(Connection conn) throws Exception{
    String sql = " create table tkpjb26776242_tab ( "
                 + "  col1 clob, "
                 + " col2 clob , "
                 + " col3 clob INVISIBLE, "
                 + " col4 clob INVISIBLE, "
                 + " col5 varchar2(200), "
                 + " col6 varchar2(200), "
                 + " col7 varchar2(200) INVISIBLE, "
                 + " col8 varchar2(200) INVISIBLE, "
                 + " check (col2 IS JSON), "
                 + " check (col4 IS JSON), "
                 + " check (col6 IS JSON), "
                 + " check (col8 IS JSON))";
    
    Util.doSQL(conn, sql);
  }
  
  private void dropTable(Connection conn) throws Exception{
    String sql = " drop table tkpjb26776242_tab";
    
    Util.trySQL(conn, sql);
  }
    ...

2.10 暗黙的結果のサポート

Oracle Databaseで、ストアド・プロシージャで実行されたSQL文の結果がクライアント・アプリケーションに暗黙的に返されるようになり、明示的にREF CURSORを使用する必要がなくなりました。

次のメソッドを使用して、PL/SQLプロシージャまたはブロックで戻された暗黙的な結果を取得し処理できます。

メソッド 説明

getMoreResults

結果セットで使用できる結果があるかどうかを確認します。

getMoreResults(int)

オーバーロードされたメソッドなどの結果セットで使用できる結果があるかどうかを確認します。このメソッドはintパラメータを受け入れます。値は次のいずれかです。

  • KEEP_CURRENT_RESULT

  • CLOSE_ALL_RESULTS

  • CLOSE_CURRENT_RESULT

getResultSet

実行されたPL/SQL文から暗黙的結果を繰り返し取得します。

ノート:

  • サーバー側の内部ドライバであるkprbは、暗黙的結果の情報のフェッチをサポートしていません。

  • SELECT問合せのみを暗黙的に戻すことができます。

  • アプリケーションは順次、各結果セットを取得しますが、順序に依存しない結果セットから行をフェッチできます。

次のように、プロシージャでfooをコールするとします。

 create procedure foo as
  c1 sys_refcursor;
  c2 sys_refcursor;
begin
  open c1 for select * from hr.employees;
  dbms_sql.return_result(c1); --return to client
  -- open 1 more cursor
  open c2 for select * from hr.departments;
  dbms_sql.return_result (c2); --return to client
end;
 

次のコードの抜粋に、getMoreResultsメソッドを使用してPL/SQLプロシージャによって戻された暗黙的結果を取得する方法を示します。

例1

String sql = "begin foo; end;";
...
Connection conn = DriverManager.getConnection(jdbcURL, user, password);
 try {
        Statement stmt = conn.createStatement (); 
        stmt.executeQuery (sql);
 
        while (stmt.getMoreResults())
        {
              ResultSet rs = stmt.getResultSet();
              System.out.println("ResultSet");
              while (rs.next())
             {   
                   /* get results */
             }
         }
      }

次のように、別のプロシージャでfooをコールするとします。

create or replace procedure foo asc1 sys_refcursor; c2 sys_refcursor; c3 sys_refcursor; begin   open c1 for 'select * from hr.employees';
dbms_sql.return_result (c1);-- cursor 2open c2 for 'select * from hr.departments';
dbms_sql.return_result (c2);-- cursor 3open c3 for 'select first_name from hr.employees';
dbms_sql.return_result (c3); end;

次のコードの抜粋に、getMoreResults(int)メソッドを使用してPL/SQLプロシージャによって戻された暗黙的結果を取得する方法を示します。

例2

String sql = "begin foo; end;";
...
Connection conn = DriverManager.getConnection(jdbcURL, user, password);
 
try {
        Statement stmt = conn.createStatement (); 
        stmt.executeQuery (sql);
        ResultSet rs = null; 
     
        boolean retval = stmt.getMoreResults(Statement.KEEP_CURRENT_RESULT))
        if (retval)
        {
            rs = stmt.getResultSet();
            System.out.println("ResultSet");
            while (rs.next())
            {   
                /* get results */
            }
        }
 
        /* closes open results */
        retval = stmt.getMoreResults(Statement.CLOSE_ALL_RESULTS);
 
        if (retval) 
        {
            System.out.println("More ResultSet available");
            rs = stmt.getResultSet();
            System.out.println("ResultSet");
            while (rs.next())
            {   
                /* get results */
            }
        }
  
        /* close current result set */
        retval = stmt.getMoreResults(Statement.CLOSE_CURRENT_RESULT);
        
        if(retval)
        {
            System.out.println("More ResultSet available");
            rs = stmt.getResultSet();
            while (rs.next())
            {
                /* get Results */
        
            }
        }
    }

2.11 軽量接続検証のサポート

Oracle Databaseリリース18c以降、JDBC Thinドライバは軽量接続検証をサポートしています。軽量接続検証を使用すると、JDBCアプリケーションは、データベースへのラウンドトリップを必要としない、長さ0のNSデータ・パケットを送信することで、接続の有効性を検証できます。

Oracle Databaseの18c以前のリリースでは、接続の有効性をテストするためにisValid(timeout)メソッドをコールすると、Oracle JDBCドライバではピンポン・プロトコルが使用されます。これは、データベースへの完全なラウンドトリップを行うため、負荷の高い操作になります。Oracle Databaseリリース18cからは、isValid(timeout)メソッドは空のパケットをデータベースに送信し、その応答を待機しません。そのため、接続検証が高速になり、アプリケーションのパフォーマンスが改善されます。

軽量接続検証はデフォルトで無効になっています。この機能を有効にするには、oracle.jdbc.defaultConnectionValidation接続プロパティの値をSOCKETに設定する必要があります。このプロパティが設定されている場合、isValid(timeout)メソッドをコールすると、JDBCドライバによって軽量接続検証が実行されます。

ノート:

  • 軽量接続検証は、基礎となるソケット状態のみをチェックします。isValid(timeout)メソッドがtrueを返した場合、つまり、接続が有効であるとみなされた場合、この検証では、サーバーが到達不能(デッド・ソケット)ではないことのみが保証されます。サーバー・プロセスに関するステータス(実行されているかどうかなど)は提供されません。ただし、デフォルトでは、つまり、軽量接続検証が有効でない場合、isValid(timeout)メソッドは、クライアントとサーバー間のネットワークが損なわれていないかどうかを確認します。

  • この機能は、JDBC Thinドライバのみでサポートされます。

軽量接続検証の新しいAPI

  • oracle.jdbc.defaultConnectionValidation

    この接続プロパティは、接続検証のレベルを指定します。このプロパティに指定できる値は、NONELOCALSOCKETNETWORKSERVERおよびCOMPLETEです。これらの値では大文字と小文字が区別され、これらの値以外の値を設定すると、例外がスローされます。デフォルト値はNETWORKです。

  • public boolean isValid(ConnectionValidation validation_level, int timeout) throws SQLException

    既存のisValid(timeout)メソッドの新しいバリエーションでは、検証のレベル(validation_level)とtimeoutという2つのパラメータを指定できます。最初のパラメータは、接続検証のレベルを指定します。

例2-2 軽量接続検証の例

次のコード・スニペットに、軽量接続メカニズムを実装する方法を示します。

    ...
    OracleDataSource ods = new OracleDataSource();
    ods.setURL(url);
    ods.setUser(user);
    ods.setPassword(password);
    Connection conn = ods.getConnection();
    try{
          boolean isValid = ((OracleConnection)conn).
                           		isValid(ConnectionValidation.SOCKET,timeout);                          
          System.out.println("Connection isValid = "+isValid);
    }
    catch (Exception ex)
   {
         System.out.println("Exception :" + ex);
         ex.printStackTrace();
    }
    ...    ...

2.12 データベース・ノードの優先度付け解除のサポート

Oracle Database 12cリリース2 (12.2.0.1)以降、JDBCドライバではデータベース・ノードの優先度付け解除がサポートされています。ノードが失敗すると、JDBCではこのノードの優先度付けを次の10分間解除します。これはデフォルトの失効時間です。たとえば、3つのノード(A、B、C)があり、ノードAが停止した場合、接続が割り当てられるのは、まずノードBおよびCからで、次にノードAとなります。デフォルトの失効時間の後、ノードAの優先度付けは解除されなくなります。つまり、接続は使用可能な3つのノードから割り当てられます。また、デフォルトの失効時間にノードAへの接続試行が成功すると、ノードAは優先度付け解除済ノードとみなされなくなります。ユーザーは、oracle.net.DOWN_HOSTS_TIMEOUTシステム・プロパティを使用して、優先度付け解除のデフォルトの失効時間を指定できます。

たとえば、次のURLのscan_listener0は、IPアドレスを取得すると、ip1ip2およびip3のIPアドレスが構成されています。ip1の優先度付けが解除されている場合、IPアドレスの試行の順序はip2ip3ip1となります。すべてのIPアドレスを使用できない場合、node_1およびnode_2を試行した後、最後にホスト全体が試行されます。

(DESCRIPTION_LIST=  
    (DESCRIPTION=
        (ADDRESS_LIST=
            (ADDRESS=(PROTOCOL=tcp)(HOST=scan_listener0)(PORT=1521))
            (ADDRESS=(PROTOCOL=tcp)(HOST=node_1)(PORT=1528))              
            (ADDRESS=(PROTOCOL=sdp)(HOST=node_2)(PORT=1527))
        )
        (ADDRESS_LIST=
            (ADDRESS=(PROTOCOL=tcp)(HOST=node_3)(PORT=1528))
        )              
        (CONNECT_DATA=(SERVICE_NAME=cdb3))
    )
    (DESCRIPTION=
        (ADDRESS=(PROTOCOL=tcp)(HOST=node_0)(PORT=1528))
        (CONNECT_DATA=(SERVICE_NAME=cdb3))
    )
)

2.13 Traffic DirectorモードのOracle Connection Managerのサポート

Oracle Databaseリリース18c以降、JDBCドライバでは、Traffic DirectorモードのOracle Connection Managerをサポートします。これは、データベース・クライアントとデータベース・インスタンスの間に常駐するプロキシ・サーバーです。

JDBCクライアントは、Traffic DirectorモードのOracle Connection Managerに接続し、そこからターゲットOracle Databaseに接続できます。クライアントは、Traffic DirectorモードのOracle Connection Managerが適切なターゲット・データベースにインターセプト、解析およびリレーするTwo-Task Common (TTC)メッセージの形式でリクエストを送信します。レスポンスがデータベースから受信されると、Traffic DirectorモードのOracle Connection Managerは、TTCメッセージを介してレスポンスをクライアントに転送します。

次の図は、Traffic DirectorモードのOracle Connection Managerのアーキテクチャを示しています。

図2-1 Traffic DirectorモードのOracle Connection Managerのアーキテクチャ

図2-1の説明が続きます
「図2-1 Traffic DirectorモードのOracle Connection Managerのアーキテクチャ」の説明

関連項目:

この章の項目は次のとおりです。

2.13.1 Traffic DirectorモードのOracle Connection Managerの実行モード

Traffic DirectorモードのOracle Connection Managerは次のいずれかの接続モードで実行できます。

  • プールされた接続モード

    プールされた接続モードは、プロキシ常駐接続プーリングと呼ばれる新機能を使用します。これは、データベース常駐接続プーリング(DRCP)のプロキシ対応モードです。プロキシ常駐接続プーリングは、少数のデータベース接続に対して大量のクライアント接続を多重化するため、データベース上の接続負荷を軽減します。Oracle Database 12cリリース1 (12.1)以降のJDBCドライバを使用するアプリケーションは、この接続モードを使用できます。

    ノート:

    プール接続モードは、DRCP対応の接続プールを使用するクライアントで使用すると最適な結果が得られます。
  • プールされていない接続モードまたは専用接続モード

    プールされていない接続モードまたは専用接続モードは、サポートされている任意のOracle Database JDBCドライバを使用するアプリケーションで使用できます。ただし、接続の多重化などの一部の機能は、このモードでは使用できません。

2.13.2 Traffic DirectorモードのOracle Connection Managerの利点

この項では、Traffic DirectorモードのOracle Connection Managerがアプリケーションにとってどのような利点があるかを説明します。

  • 透過的パフォーマンスの強化: Traffic DirectorモードのOracle Connection Managerでは、プールされたモードとプールされていないモードの両方で文キャッシュ、行プリフェッチおよび結果セット・キャッシュが自動的に有効になります。

  • 接続の多重化: Proxy Resident Connection Pooling (PRCP)を使用すると、Traffic Directorモード(プールされたモード)のOracle Connection Managerによって、データベースでの透過的な接続時ロード・バランシングおよびランタイム・ロード・バランシングが提供されます。Traffic DirectorモードでOracle Connection Managerの複数のインスタンスを使用する場合、クライアント側の接続時ロード・バランシングの実装またはBIG-IPやNGINXなどのロード・バランサによって、アプリケーションのスケーラビリティを向上させることができます。

  • アプリケーション停止時間ゼロ: Traffic DirectorモードのOracle Connection Managerでは、計画済データベース・メンテナンス中および計画外データベース停止中のアプリケーション停止時間がゼロになります。計画外データベース停止の場合、ほとんどの読取りワークロードでアプリケーションの停止時間がゼロになります。計画済のデータベース・メンテナンスまたはプラガブル・データベース(PDB)の再配置では、この項で説明するように、プールされたモードとプールされていないモードに対して異なる手法が使用されます。

    • プールされたモード:

      計画済の停止の場合、Traffic DirectorモードのOracle Connection ManagerはOracle Notification Service (ONS)イベントに応答します。プロキシ常駐接続プールのデータベース接続を使用し、リクエストを適切なデータベースにリダイレクトします。リクエストが完了すると、プールから接続が排出されます。

      PDBの再配置の場合、Traffic DirectorモードのOracle Connection Managerでは、ONSが構成されていない場合でも動作するインバンド・クライアント通知メカニズムが使用されます。この機能は、Oracle Databaseリリース18c以降でのみ使用できます。

    • プールされていないモードまたは専用モード

      このモードでは、Traffic DirectorモードのOracle Connection Managerは、Oracle Databaseの次の機能のいずれかを使用します。

      • リクエスト境界でサービスを停止する継続的なアプリケーション可用性
      • 単純な状態を再接続してリストアするための透過的アプリケーション・フェイルオーバー(TAF)
  • 高可用性: Traffic DirectorモードのOracle Connection Managerは、単一障害点を回避するために次の手法を実装し、高可用性を保証します。

    • Traffic DirectorモードのOracle Connection Managerの複数のインスタンスは、接続文字列でロード・バランサまたはクライアント側のロード・バランシングを使用します。

    • Traffic DirectorモードのOracle Connection Managerインスタンスは、ローリング・アップグレードをサポートします。

    • 計画済の停止の場合、Traffic DirectorモードのOracle Connection Managerは、クライアントからの既存の接続の正常なクローズを実装します。

    • Traffic DirectorモードのOracle Connection Managerは、インバンド通知をOracle Databaseリリース18c以降のクライアントに送信し、ONS通知をOracle Databaseリリース18cより前のサポートされているすべてのクライアントに送信します。

  • セキュリティ: Traffic DirectorモードのOracle Connection Managerは、次の方法でアプリケーションにセキュリティを提供します。

    • Transmission Control Protocol Secure (TCPS)プロトコルをサポートしています。

    • IPアドレス、サービス名およびTransport Layer Security (TLS)ウォレットに基づいてファイアウォールを作成します。

    • サービス拒否攻撃とファジング攻撃からの保護を提供します。

    • オンプレミスのOracle DatabaseとOracle Cloudの間のデータベース・トラフィックのセキュアなトンネリングを提供します。

  • テナント分離: Traffic DirectorモードのOracle Connection Managerは、メモリーの増加と処理能力の拡張のためのテナント分離を提供します。

2.14 JDBCプログラムでのストアド・プロシージャ・コール

この項では、Oracle JDBCドライバが次の種類のストアド・プロシージャをサポートする方法について説明します。

2.14.1 PL/SQLストアド・プロシージャ

JDBCでは、JDBCエスケープ構文またはPL/SQLブロック構文を使用して、PL/SQLプロシージャ/ファンクションおよび匿名ブロックの起動をサポートしています。次のPL/SQLコールは、すべてのOracle JDBCドライバで動作します。

// JDBC escape syntax
CallableStatement cs1 = conn.prepareCall
                       ( "{call proc (?,?)}" ) ; // stored proc
CallableStatement cs2 = conn.prepareCall
                       ( "{? = call func (?,?)}" ) ; // stored func
// PL/SQL block syntax
CallableStatement cs3 = conn.prepareCall
                       ( "begin proc (?,?); end;" ) ; // stored proc
CallableStatement cs4 = conn.prepareCall
                       ( "begin ? := func(?,?); end;" ) ; // stored func

Oracle構文の例として、ストアド・ファンクションを作成するPL/SQLコードの一部を示します。このPL/SQLファンクションでは文字列を取得して接尾辞を連結します。

create or replace function foo (val1 char)
return char as
begin
   return val1 || 'suffix';
end;

JDBCプログラム内のファンクションの起動は、次のようになります。

OracleDataSource ods = new OracleDataSource();
ods.setURL("jdbc:oracle:oci:@<hoststring>");
ods.setUser("HR");
ods.setPassword("hr");
Connection conn = ods.getConnection();

CallableStatement cs = conn.prepareCall ("begin ? := foo(?); end;");
cs.registerOutParameter(1,Types.CHAR);
cs.setString(2, "aa");
cs.execute();
String result = cs.getString(1);

2.14.2 Javaストアド・プロシージャ

JDBCを使用して、SQLインタフェース経由でJavaストアド・プロシージャをコールできます。Javaストアド・プロシージャをコールするための構文は、正しく公開されていると仮定すると、PL/SQLストアド・プロシージャをコールするための構文と同じです。正しく公開されているとは、つまり、Oracleデータ・ディクショナリに公開するためのコール仕様を記述していることを意味します。アプリケーションでJavaネイティブ・インタフェースを使用してJavaストアド・プロシージャをコールすると、static Javaメソッドを直接起動できます。

2.15 SQL例外の処理について

エラー状況を処理するために、Oracle JDBCドライバはSQL例外をスローし、java.sql.SQLExceptionクラスまたはそのサブクラスのインスタンスを作成します。エラーはJDBCドライバまたはデータベース自体のいずれかで発生する可能性があります。表示されるメッセージには、エラーおよびエラーを発行したメソッドの説明が含まれます。ランタイム情報が追加されることもあります。

JDBC 3.0では、SQLExceptionという単一の例外しかサポートされていません。ただし、エラーはカテゴリが多いので、区別すると便利です。そのため、JDBC 4.0では様々なカテゴリのエラーを特定するためにSQLException例外の一連のサブクラスが導入されています。

基本例外処理には、エラー・メッセージの取出し、エラー・コードの取出し、SQL状態の取出しおよびスタック・トレースの出力が含まれます。SQLExceptionクラスには、使用可能な場合にこのようなすべての情報を取り出す機能があります。

エラー情報の取出し

SQLExceptionクラスの次のメソッドで、基本エラー情報を取り出すことができます。

  • getMessageクラスには、使用可能な場合にこのようなすべての情報を取り出す機能があります。

  • getErrorCodeクラスには、使用可能な場合にこのようなすべての情報を取り出す機能があります。

  • getSQLStateクラスには、使用可能な場合にこのようなすべての情報を取り出す機能があります。

次の例はgetMessage()メソッド・コールからの情報を出力します。

catch(SQLException e)
{
   System.out.println("exception: " + e.getMessage());
}

これはJDBCドライバで発生したエラーに対して、次のような情報を出力します。

exception: Invalid column type

ノート:

Oracleでサポートされている言語と文字セットでエラー・メッセージ・テキストを使用できます。

スタック・トレースの出力

SQLExceptionクラスには、スタック・トレースを出力するためのprintStackTrace()メソッドがあります。このメソッドは、Throwableオブジェクトのスタック・トレースを標準エラー・ストリームに出力します。出力のために、java.io.PrintStreamオブジェクトまたはjava.io.PrintWriterオブジェクトも指定できます。

次のコード・フラグメントは、SQLの例外を捕捉してスタック・トレースを表示する方法を示しています。

try { <some code> } 
catch(SQLException e) { e.printStackTrace (); } 
 

JDBCドライバでエラーを処理する方法を説明するために、次のコードでは不適切な列索引を使用していると仮定します。

// Iterate through the result and print the employee names 
// of the code 
 
try { 
  while (rset.next ()) 
      System.out.println (rset.getString (5));  // incorrect column index
}
catch(SQLException e) { e.printStackTrace (); } 
 

列索引が不適切であると仮定すると、このプログラムの実行によって次のエラー・テキストが生成されます。

java.sql.SQLException: Invalid column index
at oracle.jdbc.OracleDriver.OracleResultSetImpl.getDate(OracleResultSetImpl.java:1556)
at Employee.main(Employee.java:41)