Oracle Java Database Connectivity(JDBC)ドライバは、様々なバージョンのJDBC標準機能をサポートしています。Oracle Database 11gリリース2(11.2)では、Oracle JDBCドライバが強化され、JDBC 4.0標準がサポートされました。これらの機能は、oracle.jdbcパッケージとoracle.sqlパッケージによって提供されます。これらのパッケージでは、Java Development Kit(JDK)リリース1.5と1.6がサポートされています。この章では、Oracle JDBCドライバでのJDBC標準のサポートについて説明します。この章には次の項目があります。
標準のJDBC 2.0の機能は、JDK 1.2以降のバージョンでサポートされています。考慮すべき点が3つあります。
オブジェクト、配列、ラージ・オブジェクト(LOB)などのデータ型に対するサポート。このサポートは、標準java.sqlパッケージを介して処理されます。
結果セット拡張やバッチ更新などの標準機能に対するサポート。このサポートは、JDK 1.2.x以上では、Connection、ResultSetおよびPreparedStatementなどの標準オブジェクトを介して処理されます。
JDBC 2.0 Optional Packageの機能など、Standard Extension Application Program Interface(API)とも呼ばれる拡張機能に対するサポート。たとえばデータソース、接続プーリングおよび分散トランザクションなどがあげられます。
この項の内容は次のとおりです。
| 注意:1.5より前のJDKのバージョンは、もうサポートされていません。 oracle.jdbc2パッケージは削除されました。 | 
Oracle JDBCは、標準java.sqlパッケージ内のインタフェースの実装による標準JDBC 2.0機能を含む、JDK 1.5およびJDK 1.6を完全にサポートしています。これらのインタフェースは、oracle.sqlパッケージとoracle.jdbcパッケージ内のクラスによって、適宜実装されます。
ojdbc5.jarのJDBCクラスを使用するJDK 1.5環境では、スクロール可能結果セット、更新可能結果セット、バッチ更新などのJDBC 2.0機能は、標準のJDBC 2.0インタフェースによって指定されたメソッドを介してサポートされます。
データソース、接続プーリングおよび分散トランザクションなどのJDBC 2.0 Optional Packageの各機能は、JDK 1.2.x以上の環境でサポートされます。
標準javax.sqlパッケージとそのインタフェースを実装するクラスは、Oracle Databaseでパッケージ化されたJavaアーカイブ(JAR)ファイルに格納されています。
標準のJDBC 3.0の機能は、JDK 1.4以降のバージョンでサポートされています。表3-1では、Oracle Database 11gリリース2(11.2)でサポートしているJDBC 3.0機能と、各機能に関する詳細の参照先を示しています。
表3-1 JDBC 3.0機能の主な領域
| 機能 | コメントと参照 | 
|---|---|
| トランザクション・セーブポイント | 詳細は、「トランザクション・セーブポイント」を参照してください。 | 
| 文キャッシュ | 接続プーリングによってコンパイルされたSQL文を再使用します。第20章「文キャッシュと結果セット・キャッシュ」を参照してください。 | 
| ローカル・トランザクションとグローバル・トランザクションの切替え | 「ローカル・トランザクションとグローバル・トランザクションの切替え」を参照してください。 | 
| LOBの変更 | 「JDBC 3.0のLOBインタフェース・メソッド」を参照してください。 | 
| 名前付きSQLパラメータ | 「インタフェースoracle.jdbc.OracleCallableStatement」および「インタフェースoracle.jdbc.OraclePreparedStatement」を参照してください。 | 
| RowSet | 第18章「JDBC RowSet」を参照してください。 | 
| 自動生成キーの取出し | 「自動生成キーの取出し」を参照してください。 | 
| 結果セットの保持機能 | 「結果セットの保持機能」を参照してください。 | 
この項では、Oracle JDBCドライバによってサポートされている次のJDBC 3.0機能について説明します。
JDBC 3.0の仕様はセーブポイントをサポートしており、トランザクション内でより細かい境界設定をすることができます。アプリケーションはトランザクション内にセーブポイントを設定して、セーブポイントより後に行われたすべての作業をロールバックすることができます。セーブポイントを使用することで、トランザクションの原子性が緩和されます。セーブポイントを持つトランザクションは、トランザクションのコンテキスト外部では1つの単位のように見えるという点で原子的ですが、トランザクション内で動作しているコードは部分的な状態を維持することができます。
| 注意:セーブポイントがサポートされるのは、ローカル・トランザクションのみです。グローバル・トランザクション内でセーブポイントを指定すると、 SQLException例外が発生します。 | 
セーブポイントを作成するには、java.sql.Savepointインスタンスを戻すConnection.setSavepointを使用します。
セーブポイントには名前がある場合とない場合があります。セーブポイントの名前を指定するには、setSavepointメソッドに文字列を指定します。名前が未指定の場合は、整数のIDが割り当てられます。名前の取出しにはgetSavepointNameメソッドを使用します。IDの取出しにはgetSavepointIdメソッドを使用します。
| 注意:名前付けされていないセーブポイントから名前を取り出そうとしたり、名前付けされているセーブポイントからIDを取り出そうとしたりすると、 SQLException例外がスローされます。 | 
セーブポイントまでロールバックするには、Connection.rollback(Savepoint svpt)メソッドを使用します。解放されているセーブポイントまでロールバックしようとすると、SQLException例外がスローされます。
使用中のデータベースでセーブポイントがサポートされているかどうかを調べるには、oracle.jdbc.OracleDatabaseMetaData.supportsSavepointsメソッドをコールします。セーブポイントが使用可能な場合はtrue、そうでない場合はfalseが戻されます。
多くのデータベース・システムでは、行が挿入される際に一意のキー・フィールドが自動的に生成されます。Oracle Databaseでは、順序とトリガーにより、この機能が提供されます。JDBC 3.0には、自動生成キーの取出し機能が導入され、生成された値を取り出せるようになりました。JDBC 3.0では、自動生成キーの取出し機能をサポートするために、次のインタフェースが拡張されました。
java.sql.DatabaseMetaData
java.sql.Connection
java.sql.Statement
これらのインタフェースには、自動生成キーの取出しをサポートするメソッドが用意されています。ただし、この機能はINSERT文が処理される場合にのみサポートされます。その他のデータ操作言語(DML)文の処理では、自動生成キーの取出しは実施されません。
| 注意:Oracleのサーバー側内部ドライバでは、自動生成キーの取出し機能をサポートしていません。 | 
キー列を明示的に指定しないと、Oracle JDBCドライバでは取り出す列を特定できません。特定できるのは、列名または列索引の配列が使用されている場合です。ただし、int型のStatement.RETURN_GENERATED_KEYSフラグが使用されている場合、Oracle JDBCドライバではこれらの列を特定できません。int型フラグを使用して自動生成キーが戻るように指定した場合は、ROWID擬似列がキーとして戻ります。このROWIDは、ResultSetオブジェクトからフェッチして、他の列を取り出すために使用できます。
次のコードは、自動生成キーの取出しを示しています。
/** SQL statements for creating an ORDERS table and a sequence for generating the
  * ORDER_ID.
  *
  * CREATE TABLE ORDERS (ORDER_ID NUMBER, CUSTOMER_ID NUMBER, ISBN NUMBER,
  * DESCRIPTION NCHAR(5))
  *
  * CREATE SEQUENCE SEQ01 INCREMENT BY 1 START WITH 1000
  */
...
String cols[] = {"ORDER_ID", "DESCRIPTION"};
// Create a PreparedStatement for inserting a row into the ORDERS table.
OraclePreparedStatement pstmt = (OraclePreparedStatement)
conn.prepareStatement("INSERT INTO ORDERS (ORDER_ID, CUSTOMER_ID, ISBN,  DESCRIPTION) VALUES (SEQ01.NEXTVAL, 101,
 966431502, ?)", cols);
char c[] = {'a', '\u5185', 'b'};
String s = new String(c);
pstmt.setNString(1, s);
pstmt.executeUpdate();
ResultSet rset = pstmt.getGeneratedKeys();
...
前の例では、シーケンス( SEQ01)がORDER_ID列の値を生成するために作成されます。値は、1000から始まり、シーケンスが処理されて次の値が生成されるたびに1ずつ増加します。OraclePreparedStatementオブジェクトは、ORDERS表に行を挿入するために作成されています。
表3-2と表3-3では、Oracle独自のメソッドとJDBC 3.0標準メソッドとの間の変換を示しています。
表3-2 等価のBLOBメソッド
| Oracle独自のメソッド | JDBC 3.0標準メソッド | 
|---|---|
| 
 | 
 | 
| 
 | 
 | 
| 
 | 
 | 
| 
 | 
 | 
表3-3 等価のCLOBメソッド
| Oracle独自のメソッド | JDBC 3.0標準メソッド | 
|---|---|
| 
 | 
 | 
| 該当なし | 
 | 
| 
 | 
 | 
| 
 | 
 | 
| 
 | 
JDBC 4.0標準は、JDK 1.6以降のバージョンでサポートされています。Oracle Database 11gリリース2(11.2)のJDBCドライバでは、JDBC 4.0標準がサポートされています。
| 注意: 
 | 
Oracle Database 11gリリース2(11.2)のJDBCドライバでは、次のような機能を利用できます。
ラッパー・パターンは、Javaアプリケーションで使用される一般的なコーディング・パターンで、データソース固有の従来のJDBC APIを超える機能を提供します。実際のリソースを表すプロキシ・クラス・インスタンスとしてラップされているリソースにアクセスする場合に、これらの拡張機能を使用する必要があることがあります。JDBC4.0では、リソース代理への直接アクセスを許可するために、プロキシによって表されるこれらのラップされたリソースにアクセスするための標準メカニズムを記述するWrapperインタフェースが導入されています。
Wrapperインタフェースでは、次の2つのメソッドが提供されています。
public boolean isWrapperFor(Class<?> iface) throws SQLException;
public <T> T unwrap(Class<T> iface) throws SQLException;
SQLデータを表すものを除く他のJDBC4.0インタフェースはすべてこのインタフェースを実装しています。これには、Connection、Statementとそのサブタイプ、ResultSetおよびメタデータ・インタフェースが含まれます。
JDBC 4.0標準で最も重要な更新内容の1つはSQL 2003標準で定義されたXMLデータ型のサポートです。現在、JDBCは、SQL/XMLデータベース・データ型 をサポートするためのマッピング・インタフェースを提供しています(java.sql.SQLXML)。この新しいJDBCインタフェースは、XMLの、Javaネイティブのバインディングを定義し、それにより、データベースXMLデータの処理をより簡単、より効率的にしています。
| 注意: 
 | 
java.sql.ConnectionインタフェースでcreateSQLXMLメソッドをコールすることによって、XMLのインスタンスを作成することができます。このメソッドは、空のXMLオブジェクトを戻します。
次に示すように、PreparedStatement、CallableStatementおよびResultSetインタフェースは拡張され、適切なgetterメソッドとsetterメソッドが用意されました。
PreparedStatement: メソッドsetSQLXMLが追加されました。
CallableStatement: メソッドgetSQLXMLおよびsetSQLXMLが追加されました。
ResultSet: メソッドgetSQLXMLが追加されました。
oracle.jdbc.getObjectReturnsXMLTypeプロパティ
Oracle Database 10gと、Oracle Database 11gの初期バージョンでは、Oracle JDBCドライバは、Oracleの独自規格の拡張機能を介してOracle SQL XML型(XMLType)をサポートしていました。XML値はoracle.xdb.XMLTypeクラスのインスタンスによって表され、SQL XMLType値はJDBC標準のgetObject、setObjectおよびupdateObjectの各メソッドを介して読取りと、設定が行われていました。
JDBC標準では、SQL XML型の列でコールされた場合、java.sql.SQLXML型のインスタンスを戻すことを、getObjectメソッドに求めています。しかし、旧バージョンのOracle JDBCドライバでは、oracle.xdb.XMLTypeのインスタンスが戻されます。これは、JDBC標準に準拠していません。
Oracle JDBCドライバの現在のリリースでは新しい接続プロパティ( oracle.jdbc.getObjectReturnsXMLType)が導入され、JDBC標準に準拠しています。このプロパティをfalseに設定すると、getObjectメソッドはjava.sql.SQLXML型のインスタンスを戻します。そうするには、javacでプログラムをコンパイルする際に次のコマンドライン・オプションを使用します。
-Doracle.jdbc.getObjectReturnsXMLType="false"
oracle.xdb.XMLTypeを使用する既存のOracle独自規格のSQL XMLTypeサポートに依存している場合、次のコマンドライン・オプションを使用することにより、このプロパティの値をtrueに戻すことができます。
-Doracle.jdbc.getObjectReturnsXMLType="true"
oracle.jdbc.getObjectReturnsXMLTypeプロパティの値は、trueまたはfalseのブール値を表すStringです。このプロパティの値がtrueの場合、getObjectメソッドは、SQL XMLTypeの列に対してコールされるとoracle.xdb.XMLTypeインスタンスを戻します。これが、oracle.jdbc.getObjectReturnsXMLTypeプロパティのデフォルト値です。このプロパティの値がfalseの場合、getObjectメソッドはjava.sql.SQLXMLインスタンスを戻します。これは、標準のJDBC準拠モードです。
| 注意: oracle.jdbc.getObjectReturnsXMLTypeプロパティは、getObjectメソッドの結果のみに影響を及ぼします。他のメソッドはすべて、プロパティの値に関係なく、標準のJDBC 4.0に準拠します。 | 
例
例3-1 SQLXMLデータへのアクセス
次の例は、StringからXMLのインスタンスを作成し、データベースにXMLデータを書き込み、データベースからXMLデータを取得する方法を示しています。
import java.sql.*;
import java.util.Properties;
import oracle.jdbc.pool.OracleDataSource;
 
public class SQLXMLTest
 {
 
  public static void main(String[] args) 
  {
  
  Connection conn = null;
  Statement stmt = null;
  ResultSet rs = null;
  PreparedStatement ps = null;
  
  String xml = "<?xml version=\"1.0\"?>\n" +
    "<oldjoke>\n" +
    "<burns>Say <quote>goodnight</quote>, Gracie.</burns>\n" +
    "<allen><quote>Goodnight, Gracie.</quote></allen>\n" +
    "<applause/>\n" +
    "</oldjoke>";
 
  try
  {
 
     OracleDataSource ods = new OracleDataSource();
     ods.setURL("jdbc:oracle:thin:@//localhost:1521/orcl");
     ods.setUser("scott");
     ods.setPassword("tiger");
     conn = ods.getConnection();
 
     ps = conn.prepareStatement("insert into x values (?, ?)");
     ps.setString(1, "string to string");
     SQLXML x = conn.createSQLXML();
     x.setString(xml);
     ps.setSQLXML(2, x);
     ps.execute();
     x.free();
     stmt = conn.createStatement();
     rs = stmt.executeQuery("select * from x");
     while (rs.next()) 
     {
 
       System.out.println(rs.getString(1) + "\n" + rs.getSQLXML(2).getString());
     }
 
     rs.close();
     ps.close();    
  }
 
  catch (SQLException e){e.printStackTrace ();}
 
  }
}
| 注意:空のXMLを指定してsetterメソッドをコールすると、 SQLExceptionがスローされます。getterメソッドが空のXMLを戻すことはありません。 | 
JDBC 3.0では、SQLExceptionという単一の例外しかサポートされていません。ただし、エラーはカテゴリが多いので、区別すると便利です。この機能では、様々なカテゴリのエラーを特定するために、SQLExceptionクラスのサブクラスがサポートされています。永続エラーと一時エラーの切分けが、主要な切分けになります。永続エラーは、システムの正しい動作の結果であり、常に発生します。一時エラーは、タイムアウトなど、システムの一部で障害が発生した結果であり、再発しない場合もあります。
JDBC 4.0では、一時エラー、永続エラーおよびそれらエラーの様々なカテゴリを表現するために、例外が追加されています。
また、SQLExceptionクラスとそのサブクラスは、J2SE関連の例外機能をサポートするために機能拡張されています。
JDBC 4.0では、SQLのROWID値を表現するために、java.sql.RowIdデータ型がサポートされています。ResultSetインタフェースおよびCallableStatementインタフェースで定義されているgetterメソッドを使用すると、RowId値を取り出すことができます。開発者は、パラメータ化されたPreparedStatementの中でRowId値を使用して、RowIdオブジェクトのパラメータを設定したり、更新可能な結果セットの中で使用して、列を特定のRowId値に更新したりできます。
RowIdオブジェクトは、指定された行が削除されるまで有効です。RowIdオブジェクトは、次の場合にも有効なことがあります。
作成元トランザクションの期間中。
作成元セッションの期間中。
RowIdオブジェクトが永続的に有効である期間(未定義)。
DatabaseMetaData.getRowIdLifetimeメソッドをコールすると、RowIDオブジェクトの存続期間を確認できます。
JDBC 4.0では、BLOB、CLOBおよびNCLOBオブジェクトの作成をサポートするために、Connectionインタフェースが機能拡張されています。このインタフェースでサポートされているcreateBlob、createClobおよびcreateNClobメソッドを使用すると、Blob、ClobおよびNClobオブジェクトを作成できます。
作成されたLOB(Large OBject)にデータは含まれません。java.sql.Blob、java.sql.Clobおよびjava.sql.NClobインタフェースで使用可能なAPIをコールして、これらのオブジェクトにデータを追加または取得できます。これらのオブジェクトからは、内容の全体または一部を取り出すことができます。次のコードでは、BLOBオブジェクトのオフセット200の位置から100バイトのデータを取り出す方法を示しています。
... Connection con = DriverManager.getConnection(url, props); Blob aBlob = con.createBlob(); // Add data to the BLOB object. aBlob.setBytes(...); ... // Retrieve part of the data from the BLOB object. InputStream is = aBlob.getBinaryStream(200, 100); ...
setBlob、setClobおよびsetNClobメソッドを使用して、PreparedStatementオブジェクトにLOBを入力パラメータとして渡すこともできます。updateBlob、updateClobおよびupdateNClobメソッドを使用すると、更新可能結果セット内の列値を更新できます。
これらのLOBは一時LOBで、一時LOBを使用する必要がある場合に使用します。データベース内の記憶域を永続的にするには、これらのLOBを表に書き込む必要があります。
一時LOBは、作成元のトランザクションの期間中は少なくとも有効です。ただし、トランザクションの実行期間が長いと、メモリーの使用が保証されない場合があります。次のようにLOBのfreeメソッドをコールすると、LOBを解放できます。
... Clob aClob = con.createClob(); int numWritten = aClob.setString(1, val); aClob.free(); ...
JDBC 4.0では、各国語キャラクタ・セットの型にアクセスするためのNCHAR、NVARCHAR、LONGNVARCHARおよびNCLOBというJDBC型が導入されています。これらの型は、各国語キャラクタ・セットを使用して値がエンコードされる点を除き、CHAR、VARCHAR、LONGVARCHARおよびCLOB型に類似しています。