この章では、Oracle Java Database Connectivity(JDBC)ドライバ・バージョン、データベース・バージョンおよびJava Development Kit(JDK)バージョン間の互換性について説明します。また、クライアント・インストールと構成のテスト、および簡単なアプリケーションの実行方法の基本を説明します。この章の内容は次のとおりです。
この項では、一般的な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ドライバの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.jar、ojdbc6_g.jar、ojdbc7.jarおよびojdbc7_g.jar
JDK 6およびJDK 7で使用するための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)機能にも必要です。
|
関連項目: 高速アプリケーション通知および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.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は大文字で指定する必要があることに注意してください。アスタリスク(*)はパターンです。特定のコンピュータまたはポートのみに接続する許可を付与してユーザーへの許可を制限できます。
|
関連項目: 『Oracle Database Java開発者ガイド』 |
Javaがクライアント・システムで正しく設定されたことを確認するには、ORACLE_HOME/jdbc/demoの下のsamplesディレクトリに移動します。次に、コマンドラインで次のコマンドを順に入力して、JavaコンパイラおよびJavaインタプリタがエラーなく実行されていることを確認します。
javac java
これらの各コマンドは、オプションとパラメータのリストを表示して終了します。可能であれば、jdbc/demo/samples/generic/SelectExampleなどの簡単なテスト・プログラムを使用して、コンパイルと実行の確認をしてください。
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
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アプリケーションの作成を開始できます。Oracle JDBCドライバを使用する場合は、プログラムに特定のドライバ固有情報を含める必要があります。この項では、ドライバ固有情報の追加場所と追加方法について、チュートリアルの形式で説明します。チュートリアルは、クライアントからデータベースへの接続および問合せを行うコードを作成する方法を、手順を追って説明します。
次のタスクを実行するコードを記述する必要があります。
|
注意: 最初の3つのタスク用のOracleドライバ固有情報を指定して、プログラムがJDBC Application Program Interface(API)を使用してデータベースにアクセスできるようにします。その他のタスクについては、Javaアプリケーションの場合と同様に、標準JDBC Javaコードを使用できます。 |
使用するOracle JDBCドライバの種類にかかわらず、表2-1に示されているimport文をプログラムの最初に記述する必要があります。
表2-1 JDBCドライバ用のimport文
| import文 | 提供パッケージ |
|---|---|
|
標準のJDBCパッケージ |
|
|
|
|
|
|
JDBCに対するOracleの拡張機能。これはオプションです。
Oracle型拡張機能。これはオプションです。 |
オプションとなっているOracleパッケージは、Oracle JDBCドライバの拡張機能へのアクセスを提供しますが、この項の例には必要ありません。
|
注意: ワイルド・カードのアスタリスク(*)は使用せずに、アプリケーションに必要なクラスのみをインポートすることをお薦めします。このガイドでは簡単にするためにアスタリスク(*)を使用していますが、クラスおよびインタフェースのインポート方法としてはお薦めしません。 |
最初に、OracleDataSourceインスタンスを作成する必要があります。次に、OracleDataSource.getConnectionメソッドを使用してデータベースへの接続をオープンします。取り出した接続のプロパティは、OracleDataSourceインスタンスから導出されたものです。URL接続プロパティを設定した場合は、TNSEntryName、DatabaseName、ServiceName、ServerName、PortNumber、Network Protocolおよびドライバのタイプを含む他のプロパティはすべて無視されます。
次のコードは、データソースの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で指定されたユーザー名とパスワードをオーバーライドします。 |
次の例では、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();
データベースに接続し、そのプロセスでConnectionオブジェクトを作成した後、次に、Statementオブジェクトを作成します。JDBC ConnectionオブジェクトのcreateStatementメソッドは、JDBC Statement型のオブジェクトを返します。前の項の、Connectionオブジェクトconnが作成された例の続きとして、Statementオブジェクトを作成する方法の例を示します。
Statement stmt = conn.createStatement();
データベースへの問合せを行う場合、StatementオブジェクトのexecuteQueryメソッドを使用します。このメソッドは、入力としてSQL文を受け取り、JDBC ResultSetオブジェクトを戻します。
|
注意:
|
この例の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値として実体化されます。
ResultSetとStatementオブジェクトの使用後に、明示的にこれらをクローズする必要があります。これは、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文にデータをバインドするには、PreparedStatementでsetXXXメソッドを使用します。
次の例では、プリコンパイルされた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操作にはパラメータがないため、このオブジェクトを使用しないでください。
また、データベース制限のため、 |
次の例では、再実行の前に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操作を実行し、表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文に影響を与えます。
|
注意:
|
トランザクションによりデータベースを更新すると、この更新に対応する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は、非表示列の情報のフェッチをサポートしていません。 |
次の例は、前の項で説明した処理を例証するものです。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ファイル内のエントリを指定します。
この項では、Oracle JDBCドライバが次の種類のストアド・プロシージャをサポートする方法について説明します。
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);
JDBCを使用して、SQLインタフェース経由でJavaストアド・プロシージャをコールできます。Javaストアド・プロシージャをコールするための構文は、正しく公開されていると仮定すると、PL/SQLストアド・プロシージャをコールするための構文と同じです。正しく公開されているとは、つまり、Oracleデータ・ディクショナリに公開するためのコール仕様を記述していることを意味します。アプリケーションでJavaネイティブ・インタフェースを使用してJavaストアド・プロシージャをコールすると、static Javaメソッドを直接起動できます。
今回のリリース以降、Oracle Databaseでは、ストアド・プロシージャで実行されたSQL文の結果をサポートしています。明示的にREF CURSORを使用する必要がなく、結果は暗黙的にクライアント・アプリケーションに戻されます。次のメソッドを使用して、PL/SQLプロシージャまたはブロックで戻された暗黙的な結果を取得し処理できます。
|
注意:
|
次のように、プロシージャで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 */ } } }
エラー状況を処理するために、Oracle JDBCドライバはSQL例外をスローし、java.sql.SQLExceptionクラスまたはそのサブクラスのインスタンスを作成します。エラーはJDBCドライバまたはデータベース自体のいずれかで発生する可能性があります。表示されるメッセージには、エラーおよびエラーを発行したメソッドの説明が含まれます。ランタイム情報が追加されることもあります。
JDBC 3.0では、SQLExceptionという単一の例外しかサポートされていません。ただし、エラーはカテゴリが多いので、区別すると便利です。そのため、JDBC 4.0では様々なカテゴリのエラーを特定するためにSQLException例外の一連のサブクラスが導入されています。この機能の詳細は、「JDBC 4.0標準のサポート」を参照してください。
基本例外処理には、エラー・メッセージの取出し、エラー・コードの取出し、SQL状態の取出しおよびスタック・トレースの出力が含まれます。SQLExceptionクラスには、使用可能な場合にこのようなすべての情報を取り出す機能があります。
エラー情報の取出し
SQLExceptionクラスの次のメソッドで、基本エラー情報を取り出すことができます。
次の例は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)