ヘッダーをスキップ
Oracle® Database JDBC開発者ガイド
12cリリース1 (12.1)
B71308-02
  目次へ移動
目次
索引へ移動
索引

前
 
次
 

2 スタート・ガイド

この章では、Oracle Java Database Connectivity(JDBC)ドライバ・バージョン、データベース・バージョンおよびJava Development Kit(JDK)バージョン間の互換性について説明します。また、クライアント・インストールと構成のテスト、および簡単なアプリケーションの実行方法の基本を説明します。この章の内容は次のとおりです。

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

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

下位互換性

Oracle Database 12cリリース1 (12.1) JDBCドライバは、現在サポートされているOracle Databaseリリース(11.x.0.x)で認定されています。ただし、10.2.x、10.1.x、9.2.xおよび9.0.1.xなどの旧リリースですでにサポート期間が終了しているデータベース・リリースへの接続はサポートしません。

上位互換性

既存のサポートされているJDBCドライバは、Oracle Database 12cリリース1 (12.1)で動作することが確認されています。


注意:


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

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

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

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


注意:

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

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

Oracle Java製品をインストールすると、次のディレクトリが作成されます。

  • ORACLE_HOME/jdbc

  • ORACLE_HOME /jlib

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

  • demo

    このディレクトリには、圧縮ファイルdemo.zipまたはdemo.tarが格納されています。この圧縮ファイルを解凍すると、samplesディレクトリおよびSamples-Readme.txtファイルが作成されます。samplesディレクトリには、JDBCエスケープ構文とOracle SQLの構文、PL/SQLブロック、ストリーム、ユーザー定義型、追加Oracle型拡張機能、Oracleパフォーマンス拡張機能の使用方法の例などのサンプル・プログラムが格納されています。

  • doc

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

  • lib

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

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

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

    • ojdbc6.jarojdbc6_g.jarojdbc7.jarおよびojdbc7_g.jar

      JDK 6およびJDK 7で使用するためのJDBCドライバ・クラスが含まれています。


      注意:

      • Oracle Database 11gリリース1では、バージョン5.0より前のバージョンのJDKはサポートされていません。また、ojdbc14.jarojdbc5.jarおよびclasses12.jarファイルも含まれていません。かわりに、Oracle Database 12cに含まれているojdbc6.jarファイルおよびojdbc7.jarファイルを使用できます。

      • JSE 6以降を使用している場合は、明示的にJDBCドライバをロードする必要はありません。これは、Javaランタイムが必要に応じてドライバをロードすること、そのためClass.forName("oracle.jdbc.OracleDriver")new oracle.jdbc.OracleDriver()をコードに含める必要がないことを意味します。ただし、J2SE 5.0を使用する場合は、JDBCドライバを明示的にロードする必要があります。


  • Readme.txt

    製品の他のドキュメントで説明されていない、ドライバに関するリリース固有の最新情報が記載されています。

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

  • jta.jarおよびjndi.jar

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


    注意:

    これらのファイルの詳細は、次のサイトを参照してください。

    http://www.oracle.com/technetwork/java/javaee/jta/index.html

    http://www.oracle.com/technetwork/java/jndi/index.html


  • ons.jar

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


    関連項目:

    高速アプリケーション通知およびUCPの詳細は、付録B「Oracle RAC高速アプリケーション通知」および『Oracle Universal Connection Pool for JDBC開発者ガイド』を参照してください。

環境変数の確認

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

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

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

注意:

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

JDBC OCIドライバ

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モードで実行できます。

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


関連項目:

『Oracle Database Java開発者ガイド』

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

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

javac

java

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

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 ojdbc6.jar

  • java -jar ojdbc7.jar

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 "";
    }
  }
}

JDBCでの基本的な処理

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

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

  1. パッケージのインポート

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

  3. Statementオブジェクトの作成

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

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

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

  7. データベースの変更

  8. 変更のコミット

  9. 接続のクローズ


注意:

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

パッケージのインポート

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

表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ドライバの拡張機能へのアクセスを提供しますが、この項の例には必要ありません。


注意:

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

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

最初に、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();

Statementオブジェクトの作成

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

Statement stmt = conn.createStatement();

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

データベースへの問合せを行う場合、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");

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

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

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

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

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

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

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

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

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

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

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


注意:

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

データベースの変更

DML操作

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

データベースに送信するプリコンパイルされたSQL文にデータをバインドするには、PreparedStatementsetXXXメソッドを使用します。

次の例では、プリコンパイルされたSQL文を使用して、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();
}

変更のコミット

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

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

動作 エラー・メッセージ

COMMIT

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

ROLLBACK

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


COMMITまたはROLLBACK操作を実行し、表2-2に示したエラー・メッセージを受信したときに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文もコミットします。


コミット動作の変更

トランザクションによりデータベースを更新すると、この更新に対応する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オプションにも当てはまります。

非表示列の操作

今回のリリース以降、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は、非表示列の情報のフェッチをサポートしていません。

接続のクローズ

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

conn.close();

注意:

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

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

次の例は、前の項で説明した処理を例証するものです。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ファイル内のエントリを指定します。

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

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

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

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

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

暗黙的結果のサポート

今回のリリース以降、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 */
        
            }
        }
    }

SQL例外の処理

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

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

基本例外処理には、エラー・メッセージの取出し、エラー・コードの取出し、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)