日本語PDF

2 スタート・ガイド

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

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

2.1 Oracle JDBCドライバのバージョン互換性

この項では、一般的なJDBCバージョンの互換性について説明します。

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

JDBCドライバのバージョン Database 19.x Database 18.3 Database 12.2および12.1 Database 11.2.0.4
JDBC 19.x あり あり あり あり
JDBC 18.3 あり あり あり あり
JDBC 12.2および12.1 あり あり あり あり
JDBC 11.2.0.4 あり あり あり あり

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

Oracle Databaseのバージョン リリース固有のJDBC JARファイルとサポートされているJDKバージョン
19.x ojdbc10.jarとJDK 10、JDK 11

ojdbc8.jarとJDK 8、JDK 9、JDK 11

18.3 ojdbc8.jarとJDK 8、JDK 9、JDK 10、JDK 11
12.2または12cR2 ojdbc8.jarとJDK 8
12.1または12cR1 ojdbc7.jarとJDK 7、JDK 8

ojdbc6.jarとJDK 6

11.2または11gR2 ojdbc6.jarとJDK 6、JDK 7、JDK 8

ojdbc5.jarとJDK 5

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

JDBCクライアント・インストールを検証するには、次の操作をすべて実行する必要があります。

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

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

ノート:

JDBC Thinドライバでは、データベースがインストールされているコンピュータ上にTCP/IPリスナーが必要です。

2.2.1 インストールされたディレクトリとファイルの確認

Oracle Java製品をインストールすると、この項に記載されているディレクトリなどが作成されます。

  • ORACLE_HOME/jdbc

  • ORACLE_HOME /jlib

次のディレクトリおよびファイルがORACLE_HOME/jdbcディレクトリに作成および格納されているかどうかを確認してください。

  • doc

    このディレクトリには、Oracle JDBC Application Program Interface(API)のドキュメントであるjavadoc.zipファイルが格納されています。

  • lib

    libディレクトリには、次のような必須Javaクラスが格納されています。

    • ojdbc10.jarおよびojdbc10_g.jar

      JDK 8、JDK 9およびJDK 11で使用するためのJDBCドライバ・クラスが含まれています

    • ojdbc8.jarおよびojdbc8_g.jar

      JDK 8で使用するためのJDBCドライバ・クラスが含まれています

  • orai18n.jarおよびorai18n-mapping.jar

    グローバリゼーション用およびマルチバイト文字セット・サポート用のクラスが含まれています。

  • Readme.txt

    このファイルには、ドライバに関する最新情報およびリリース固有の情報が含まれています。これらの情報は、製品の他のドキュメントには含まれていない場合があります。

次のディレクトリがORACLE_HOME /jlibディレクトリに作成され、ファイルが格納されているかどうか確認してください。

  • jta.jarおよびjndi.jar

    これらのファイルには、Java Transaction API(JTA)とJava Naming and Directory Interface(JNDI)のためのクラスが含まれています。これらのファイルが必要になるのは、分散トランザクション管理のためのJTA機能、またはネーミング・サービスのためのJNDI機能を使用する場合のみです。

  • ons.jar

    このJARファイルには、Oracle RAC高速アプリケーション通知のクラスが含まれています。これは、高速接続フェイルオーバー、実行時ロード・バランシング、Webセッション・アフィニティおよびトランザクション・アフィニティなどのユニバーサル接続プール(UCP)機能にも必要です。

2.2.2 環境変数のチェック

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

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

ORACLE_HOME/jdbc/lib/ojdbc10.jar
ORACLE_HOME/jdbc/lib/ojdbc8.jar
ORACLE_HOME/jlib/orai18n.jar

ノート:

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

JDBC OCIドライバ

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

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

    ORACLE_HOME/lib
    

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

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

    ORACLE_HOME\bin
    

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

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

JDBC Thinドライバ

JDBC Thinドライバを使用するために、他の環境変数を指定する必要はありません。ただし、JDBCサーバー側Thinドライバを使用するには、許可を設定する必要があります。

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

JDBCサーバー側Thinドライバは、データベースへの接続用のソケットをオープンします。Oracle DatabaseではJavaセキュリティ・モデルを施行しているため、SocketPermissionオブジェクトについてチェックが実行されます。

JDBCサーバー側Thinドライバを使用するには、接続するユーザーに適切な許可を付与する必要があります。次の例は、ユーザーHRに許可を付与する方法を示しています。

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

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

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

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

javac

java

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

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

JDBCドライバのバージョンを確認するには、次のサンプル・コードのように、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/hr@<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());
  }
}

次のコマンドを実行すると、JDBCドライバのバージョンを確認できます。

  • java -jar ojdbc8.jar

  • java -jar ojdbc10.jar

2.2.5 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/hr@myTNSEntry");
ods.setURL(url);
Connection conn = ods.getConnection();

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

String URL = "jdbc:oracle:thin:HR/hr@//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 非表示列のサポート

今回のリリース以降、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.6 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.7 暗黙的結果のサポート

このリリースより、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.8 軽量接続検証のサポート

Oracle Databaseリリース18c以降、JDBC Thinドライバは軽量接続検証をサポートしています。軽量接続検証を使用すると、JDBCアプリケーションは、データベースへのラウンドトリップを必要としない、長さ0のNSデータ・パケットを送信することで、接続の有効性を検証できます。Oracle Databaseの以前のリリースでは、接続の有効性をテストするために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.9 データベース・ノードの優先度付け解除のサポート

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.10 Traffic DirectorモードのOracle Connection Managerのサポート

Oracle Databaseリリース18cのJDBCドライバは、Traffic DirectorモードのOracle Connection Managerをサポートします。これは、データベース・クライアントとデータベース・インスタンスの間に配置されたプロキシです。JDBCクライアントは、Traffic DirectorモードのOracle Connection Managerに接続し、そこからターゲットOracle Databaseに接続できます。クライアントから送信されるTwo-Task Common (TTC)メッセージは、Traffic DirectorモードのOracle Connection Managerによって捕捉されます。ここで、受信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.10.1 Traffic DirectorモードのOracle Connection Managerの実行モード

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

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

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

    ノート:

    この機能は、DRCP対応の接続プールを使用しているクライアントで使用することをお薦めします。

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

    プールされていない接続モードまたは専用接続モードは、Oracle Database 11gリリース2 (11.2.0.4)以降のJDBCドライバを使用するアプリケーションで使用できます。ただし、接続の多重化などの一部の機能は、このモードでは使用できません。

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

Traffic DirectorモードのOracle Connection Managerには、次の利点があります。

  • 透過的パフォーマンスの強化および接続の多重化。これには、次のようなことが含まれます。
    • 文キャッシュ、行のプリフェッチ、および結果セット・キャッシュがすべての操作モードで自動的に有効になります。

    • プロキシ常駐接続プール(PRCP)を使用したデータベース・セッションの多重化(プールされたモードのみ)。PRCPは、データベース常駐接続プーリング(DRCP)のプロキシ・モードです。アプリケーションは、Traffic DirectorモードのOracle Connection Managerとデータベースとの間における透過的な接続時ロード・バランシングおよび実行時ロード・バランシングを利用できます。

    • Traffic DirectorモードのOracle Connection Managerに複数のインスタンスがある場合、クライアント側の接続時ロード・バランシングにより、またはロード・バランサ(BIG-IP、NGINXなど)により、アプリケーションのスケーラビリティが向上します。

  • アプリケーション停止時間ゼロ
    • 計画済のデータベース・メンテナンスまたはプラガブル・データベース(PDB)の再配置
      • プールされたモード

        Traffic DirectorモードのOracle Connection Managerは、計画済停止のOracle Notification Service (ONS)イベントに応答し、作業をリダイレクトします。要求が完了すると、Traffic DirectorモードのOracle Connection Managerのプールから接続がドレインされます。サービスの再配置は、Oracle Database 11gリリース2 (11.2.0.4)以降でサポートされています。

        PDBの再配置の場合、PDBが再配置されると、ONSが構成されていなくても、Traffic DirectorモードのOracle Connection Managerはインバンド通知に応答します(Oracle Databaseリリース18c以降のサーバーの場合のみ)。

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

        クライアントからのリクエスト境界情報がない場合、Traffic DirectorモードのOracle Connection Managerは、多くのアプリケーションの計画済停止をサポートしています(リクエストまたはトランザクションの境界を越えて単純なセッション状態やカーソル状態のみを保持する必要がある場合)。次の機能がサポートされます。
        • トランザクション境界でサービスまたはPDBを停止するか、Oracle Databaseリリース18cの継続的なアプリケーション可用性を利用してリクエスト境界でサービスを停止します

        • Traffic DirectorモードのOracle Connection Managerは、透過的アプリケーション・フェイルオーバー(TAF)のフェイルオーバーのリストアを利用して、再接続して単純な状態をリストアします。

    • 大部分が読取りのワークロードでの計画外データベース停止

  • 単一障害点をなくすためのTraffic DirectorモードのOracle Connection Managerの高可用性。これは次のようなことによってサポートされます。
    • 接続文字列でロード・バランサまたはクライアント側ロード・バランシング/フェイルオーバーを使用する、Traffic DirectorモードのOracle Connection Managerの複数のインスタンス

    • Traffic DirectorモードのOracle Connection Managerのインスタンスのローリング・アップグレード

    • 計画済停止に際して、クライアントからTraffic DirectorモードのOracle Connection Managerへの既存の接続を正常に終了

    • Oracle Databaseリリース18c以降のクライアントへのインバンド通知

    • 古いクライアントの場合、現在のリクエストのレスポンスとともに通知を送信

  • セキュリティと分離のため、Traffic DirectorモードのOracle Connection Managerには次のような備えがあります。
    • Transmission Control Protocol/Transmission Control Protocol Secure (TCP/TCPS)およびプロトコル変換をサポートするデータベース・プロキシ

    • IPアドレス、サービス名およびSecure Socket Layer/Transport Layer Security (SSL/TLS)ウォレットに基づくファイアウォール

    • マルチテナント環境でのテナントの分離

    • サービス拒否攻撃とファジング攻撃からの保護

    • オンプレミスのOracle DatabaseとOracle Cloudの間のデータベース・トラフィックのセキュア・トンネリング

2.10.3 Traffic DirectorモードのOracle Connection Managerの制限事項

次の機能は、Traffic DirectorモードのOracle Connection Managerではサポートされていません。

  • 分散トランザクション

  • アドバンスト・キューイング(AQ)

  • データベースの起動または停止のコール

  • データベース・シャーディング

  • XMLコーディング

  • SQL翻訳

  • プロキシ認証およびTLS外部認証(LDAPで使用される識別名(DN)など)

  • オブジェクトREF

  • セッションの切替え

  • スクロール可能カーソル

  • 反復ごとのDML行数

  • 暗黙的結果

  • 連続問合せ通知(CQN)

  • クライアント結果キャッシュ

  • データベース常駐接続プーリング(DRCP)でのセッション状態の修正のためのPL/SQLコールバック

  • データベース常駐接続プーリング(DRCP)での複数のタグ付け

  • アプリケーション・コンティニュイティ

  • SYSDBA、SYSOPERなどの認証

  • Real Application Security

  • PL/SQL索引付き表バインドなどのデータ型

  • 一括コピー(ODP.Netのみ)

  • 自己チューニング(ODP.Netのみ)

  • ASO暗号化およびサポートされているアルゴリズム(ASOのみ)

2.11 Memoptimized Rowstoreの高速収集のサポート

Memoptimizeされた行ストアを使用すると、モノのインターネット(IoT)などのアプリケーションで高パフォーマンス・データ・ストリーミングが可能になります。

Memoptimized Rowstoreには、次の機能があります。

  • データベースへの高頻度の単一行データの挿入処理が最適化される高速収集。
  • 高頻度の問合せのためにデータベースからのデータの高速取得を可能にする高速参照。

この機能を使用するには、次のような表を作成します。

 CREATE TABLE customers (
 id NUMBER(20,0),
 name VARCHAR2(90 BYTE),
 region VARCHAR2(10 BYTE)
 )
 segment creation immediate
 memoptimize for write
 ;

次に、JavaまたはJDBCアプリケーションからヒントを使用してINSERT文を起動します。

 INSERT /*+ MEMOPTIMIZE_WRITE */ INTO CUSTOMERS VALUES (2, 'DOS', 'NORTH');

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

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

2.12.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.12.2 Javaストアド・プロシージャ

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

2.13 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)