2 スタート・ガイド
この章では、Oracle Java Database Connectivity(JDBC)ドライバ・バージョン、データベース・バージョンおよびJava Development Kit(JDK)バージョン間の互換性について説明します。また、クライアント・インストールと構成のテスト、および簡単なアプリケーションの実行方法の基本を説明します。この章の構成は、次のとおりです。
2.1 Oracle JDBCドライバのRDBMSおよびJDKバージョン互換性
Oracle Databaseリリース19cのJDBCドライバは、サポートされているOracle Databaseリリースのすべて(19c、18c、12.2、12.1および11.2)で動作保証されています。ただし、10.2.x、10.1.x、9.2.xおよび9.0.1.xなどの旧リリースですでにサポート期間が終了しているデータベース・リリースへの接続はサポートしません。
次の表に、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
|
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
|
11.2または11gR2 | ojdbc6.jar とJDK 6、JDK 7、JDK 8
|
2.2 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クラスが格納されています。-
orai18n.jar
およびorai18n-mapping.jar
グローバリゼーション用およびマルチバイト文字セット・サポート用のクラスが含まれています。
-
ojdbc10.jar
およびojdbc10_g.jar
JDK 11で使用するためのJDBCドライバ・クラスが含まれています
-
-
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/jlib/orai18n.jar
ノート:
JTA機能およびJNDI機能を使用する場合は、jta.jar
とjndi.jar
もCLASSPATH
環境変数に指定する必要があります。
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
は大文字で指定する必要があることに注意してください。アスタリスク(*
)はパターンです。特定のコンピュータまたはポートのみに接続する許可を付与してユーザーへの許可を制限できます。
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
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ドライバを使用する場合は、プログラムに特定のドライバ固有情報を含める必要があります。この項では、ドライバ固有情報の追加場所と追加方法について、チュートリアルの形式で説明します。チュートリアルは、クライアントからデータベースへの接続および問合せを行うコードを作成する方法を、ステップを追って説明します。
次のタスクを実行するコードを記述する必要があります。
- パッケージのインポート
- データベースへの接続のオープン
- 文オブジェクトの作成
- 問合せの実行と結果セット・オブジェクトの取出し
- 結果セット・オブジェクトの処理
- 結果セット・オブジェクトとStatementオブジェクトのクローズ
- データベースの変更
- 変更のコミットについて
- 接続のクローズ
ノート:
最初の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文 | 提供パッケージ |
---|---|
|
標準のJDBCパッケージ。 |
|
|
|
JDBCに対するOracleの拡張機能。これはオプションです。
Oracle型拡張機能。これはオプションです。 |
オプションとなっているOracleパッケージは、Oracle JDBCドライバの拡張機能へのアクセスを提供しますが、この項の例には必要ありません。
ノート:
ワイルド・カードのアスタリスク(*
)は使用せずに、アプリケーションに必要なクラスのみをインポートすることをお薦めします。このガイドでは簡単にするためにアスタリスク(*)を使用していますが、クラスおよびインタフェースのインポート方法としてはお薦めしません。
2.3.2 データベースへの接続のオープン
最初に、OracleDataSource
インスタンスを作成する必要があります。次に、OracleDataSource.getConnection
メソッドを使用してデータベースへの接続をオープンします。取り出した接続のプロパティは、OracleDataSource
インスタンスから導出されたものです。URL接続プロパティを設定した場合は、TNSEntryName
、DatabaseName
、ServiceName
、ServerName
、PortNumber
、Network 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
オブジェクトの適切なget
XXX
メソッドを使用します。このXXX
には、Javaのデータ型が対応します。
たとえば、次のコードは、以前の項のResultSet
オブジェクトrset
内を反復して、各従業員名の取出しおよび出力を行います。
while (rset.next()) System.out.println (rset.getString(1));
next()
メソッドは、結果セットの最後に達するとfalse
を戻します。従業員名は、Java String
値として実体化されます。
2.3.6 結果セット・オブジェクトとStatementオブジェクトのクローズ
ResultSet
とStatement
オブジェクトの使用後に、明示的にこれらをクローズする必要があります。これは、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
オブジェクトを戻す文を定義できます。
データベースに送信するプリペアド文にデータをバインドするには、PreparedStatement
でset
XXX
メソッドを使用します。
次の例では、プリペアド文を使用して、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
操作を実行し、前の表に示したエラー・メッセージを受信したときに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.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プロシージャまたはブロックで戻された暗黙的な結果を取得し処理できます。
メソッド | 説明 |
---|---|
|
結果セットで使用できる結果があるかどうかを確認します。 |
オーバーロードされたメソッドなどの結果セットで使用できる結果があるかどうかを確認します。このメソッドは
|
|
|
実行された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の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
この接続プロパティは、接続検証のレベルを指定します。このプロパティに指定できる値は、
NONE
、LOCAL
、SOCKET
、NETWORK
、SERVER
および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アドレスを取得すると、ip1
、ip2
およびip3
のIPアドレスが構成されています。ip1
の優先度付けが解除されている場合、IPアドレスの試行の順序はip2
、ip3
、ip1
となります。すべての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 Traffic DirectorモードのOracle Connection Managerのアーキテクチャ」の説明
関連項目:
-
Traffic DirectorモードのOracle Connection Managerを設定するために
cman.ora
ファイルを構成する方法の詳細は、Oracle Database Net Services管理者ガイドを参照してください -
Traffic DirectorモードのOracle Connection Managerのパラメータの詳細は、Oracle Database Net Servicesリファレンスを参照してください
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の継続的なアプリケーション可用性を利用してリクエスト境界でサービスを停止します
-
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翻訳
-
プロキシ認証およびSSL外部認証(LDAPで使用される識別名(DN)など)
-
オブジェクトREF
-
セッションの切替え
-
スクロール可能カーソル
-
反復ごとのDML行数
-
暗黙的結果
-
連続問合せ通知(CQN)
-
クライアント結果キャッシュ
-
データベース常駐接続プーリング(DRCP)でのセッション状態の修正のためのPL/SQLコールバック
-
データベース常駐接続プーリング(DRCP)での複数のタグ付け
-
アプリケーション・コンティニュイティ
-
SYSDBA、SYSOPERなどの認証
-
Real Application Security
-
PL/SQL索引付き表バインドなどのデータ型
-
一括コピー(ODP.Netのみ)
-
自己チューニング(ODP.Netのみ)
-
ASO暗号化およびサポートされているアルゴリズム(ASOのみ)
2.11 JDBCプログラムでのストアド・プロシージャ・コール
この項では、Oracle JDBCドライバが次の種類のストアド・プロシージャをサポートする方法について説明します。
2.11.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 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)