Oracleには、Java Database Connectivity(JDBC)標準の実装を拡張するJavaクラスとインタフェースが用意されており、開発者は、Oracleデータ型にアクセスして操作し、Oracleパフォーマンス拡張機能を使用できます。この章では、JDBC標準実装を拡張するためにOracleで提供されるクラスとインタフェースの概要を示します。また、この拡張機能がサポートする主な機能についても説明します。
この章の内容は次のとおりです。
標準機能に加えて、Oracle JDBCドライバにはOracle固有型拡張機能およびパフォーマンス拡張機能があります。これらの拡張機能は、次のJavaパッケージに用意されています。
oracle.sql
Oracle形式でSQLデータを示すクラスを提供します。
oracle.jdbc
Oracle型形式でのデータベース・アクセスおよび更新をサポートするためのインタフェースを提供します。
JDBCへのOracle拡張機能には、Oracleデータベースを操作する能力を高めるいくつかの機能があります。それは次の機能です。
Oracle Database 11gリリース1(11.1)で導入された新しいJDBCメソッドstartupおよびshutdown(oracle.jdbc.OracleConnectionインタフェース内)を使用すると、Oracle Databaseインスタンスの起動と停止を実行できます。Oracle Databaseのデータベース変更通知機能もサポートされています。これらの新機能については「データベース管理」で詳しく説明します。
Oracle JDBC拡張機能の1つは、oracle.sqlパッケージの型のサポートです。このパッケージには、Oracle形式でのデータの正確な表現であるクラスが含まれています。プログラムでoracle.sql型を使用する際には、次の重要な点に注意してください。
数値型データの場合、標準Java型への変換では、データ変換プロセスの制限のために完全な精度が維持されません。データ損失の問題を最小限に抑えるには、BigDecimal型を使用してください。
特定のデータ型では、標準Java型への変換がシステムの設定によって決まる可能性があり、プログラムが予想どおりに実行されない場合があります。これは、oracle.sql型から標準Java型へのデータ変換中に発生することが知られている制限です。
プログラムの機能が、1つの表からのデータの読取りと、もう1つの表への同じデータの書込みに限定されている場合、数値および日付データについては、標準Java型と比べてoracle.sql型の方がわずかに速くなります。しかし、比較や印刷などの単純なデータ操作が1つでも含まれている場合は、標準Java型の方が速くなります。
oracle.sql.CHARはOracle形式に従うデータの正確な表現ではありません。oracle.sql.CHARはjava.lang.Stringから構成されます。java.lang.Stringの方が常に高速で、同じキャラクタ・セットを表すため、いくつかのサポートされていないキャラクタ・セットを除いて、oracle.sql.CHARを使用する利点がありません。
|
注意: 標準のJava型を使用して、既存のoracle.sql型のデータを標準のJava型に変換することを強くお薦めします。内部的には、Oracle JDBCドライバはJava標準型のパフォーマンスを最適化するように動作します。oracle.sql型は、下位互換性のためにのみサポートされており、使用は推奨されません。 |
Oracle JDBCはデータベース内の構造化オブジェクトの使用をサポートしています。ここで、オブジェクトのデータ型はネスト属性を持つユーザー定義の型です。たとえば、ユーザー・アプリケーションがEmployeeオブジェクト型を定義し、各Employeeオブジェクトが、firstname属性(文字列)、lastname属性(文字列)およびemployeenumber属性(整数値)を持つ例が考えられます。
Oracle JDBCは、Oracleオブジェクト・データ型をサポートします。JavaアプリケーションでOracleオブジェクト・データ型を使用する場合、次の点を考慮する必要があります。
Oracleオブジェクト・データ型とJavaクラス間のマップ方法
Oracleオブジェクトの属性を対応するJavaオブジェクトに格納する方法
SQLとJava形式間で属性データを変換する方法
データへのアクセス方法
Oracleオブジェクトは、弱い型指定のjava.sql.Struct、または強い型指定のカスタマイズされたクラスのいずれかにマップできます。これらの強い型指定はカスタムJavaクラスと呼ばれ、標準java.sql.SQLDataインタフェースまたはOracle拡張機能oracle.sql.ORADataインタフェースのいずれかを実装する必要があります。各インタフェースは、SQLとJavaとの間でデータ変換を行うメソッドを指定します。
|
注意: CustomDatumインタフェースにかわってORADataインタフェースが導入されました。CustomDatumインタフェースはOracle Databaseリリース11.1以降はサポート対象外になりました。 |
Oracleオブジェクトに対応するカスタムJavaクラスを作成する場合は、Oracle JPublisherユーティリティを使用することをお薦めします。Oracle JPublisherは、この作業をコマンドライン・オプションでシームレスに実行し、SQLDataまたはORADataインタフェース実装のいずれかを生成できます。
SQLDataインタフェース実装の場合、型マップによって、Oracleオブジェクト・データ型とJavaクラス間の対応関係が定義されます。型マップは、各Oracleオブジェクト・データ型に対応するJavaクラスを指定するオブジェクトです。Oracle JDBCはこれらの型マップを使用して、結果セットからOracleオブジェクト・データを取り出す際に、どのJavaクラスのインスタンス化およびデータ移入を行うかを決定します。
|
注意: 移植性が重要ではない場合は、SQLDataインタフェースのかわりにORADataインタフェースを使用することをお薦めします。ORADataインタフェースは、Oracleプラットフォームが提供する、Javaを使用するその他の機能とともに、より容易にかつ柔軟に動作します。 |
JPublisherは、カスタムJavaクラスのgetXXXメソッドを自動的に定義します。このメソッドはデータをJavaアプリケーションに取り込みます。
Oracleオブジェクト・データ型クラスには、完全修飾スキーマ名の受入れおよび復帰を行う機能があります。完全修飾スキーマ名は、次の構文になります。
{[schema_name].}[sql_type_name]
ここで、schema_nameはスキーマの名前、sql_type_nameはオブジェクトのSQL型名で、schema_nameとsql_type_nameはピリオド(.)で区切られています。
JDBCでオブジェクト型を指定するには、その完全修飾名を使用します。型名が現行ネームスペース内、つまり現行スキーマ内にある場合は、スキーマ名を入力する必要はありません。スキーマは、次の規則に従って命名されます。
スキーマ名と型名は、どちらも引用符で囲んでも囲まなくてもかまいません。ただし、CORPORATE.EMPLOYEEのように、SQL型名にピリオドが含まれている場合は、型名を引用符で囲む必要があります。
JDBCドライバは、オブジェクト名内の引用符で囲まれていない最初のピリオドを検索して、ピリオドの前の文字列をスキーマ名として使用し、ピリオドの後の文字列を型名として使用します。ピリオドが見つからない場合、JDBCドライバは現行スキーマをデフォルトとします。つまり、オブジェクト型名が現行スキーマに属している場合は、完全修飾名を指定するかわりに、スキーマを指定せずに型名のみを指定できます。これが、型名にピリオドが含まれない場合に型名を引用符で囲む理由です。
たとえば、ユーザーScottがperson.addressという型を作成し、自分のセッション内でそれを使用するとします。Scottは、スキーマ名を省略して、person.addressで型をJDBCドライバに渡します。この場合、person.addressを引用符で囲まないとピリオドが検出され、JDBCドライバはpersonをスキーマ名、addressを型名として誤って解釈してしまいます。
JDBCは、オブジェクト型名の文字列をデータベースにそのまま渡します。つまり、JDBCドライバは、オブジェクト型名が引用符で囲まれていてもその大/小文字を変更しません。
たとえば、Scott.PersonTypeがJDBCドライバにオブジェクト型名として渡されると、JDBCドライバはその文字列をそのままデータベースに渡します。別の例として、型名の文字列内に空白文字が含まれている場合、JDBCドライバは空白文字を削除しません。
Oracle Databaseでは、データ操作言語(DML)文にRETURNING句を使用できます。これによって、2つのSQL文を1文に結合できます。DML RTURNINGは、Oracle JDBC Oracle Call Interface(OCI)ドライバとOracle JDBC Thinドライバの両方でサポートされます。
この項では、Oracle JDBC拡張機能をサポートする、次のJavaパッケージについて説明します。
|
注意:
|
oracle.sqlパッケージは、SQL形式でデータへの直接アクセスをサポートしています。このパッケージは、主に、SQLデータ型とそのサポート・クラスへのJavaマッピングを提供するクラスで構成されています。実質的に、このクラスはSQLデータのJavaコンテナとして機能します。
oracle.sql.*データ型の各クラスは、すべてのデータ型に共通する機能をカプセル化したスーパークラスのoracle.sql.Datumを拡張します。その中には、JDBC 2.0準拠のデータ型に対応したクラスもあります。これらのクラスは、oracle.sql.Datumクラスを拡張すると同時に、java.sqlパッケージの標準JDBC 2.0インタフェースを実装します。
LONGおよびLONG RAWのSQL型と、REF CURSOR型カテゴリには、oracle.sql.*クラスは含まれません。これらの型では、標準JDBC機能を使用してください。たとえば、LONGまたはLONG RAWデータを、標準JDBC結果セットおよびコール可能文メソッドgetBinaryStreamおよびgetCharacterStreamを使用して入力ストリームとして取り出します。REF CURSOR型にはgetCursorメソッドを使用します。
|
注意: パッケージoracle.sql.*の方は主に下位互換性、またはOracleの少数の特定機能(OPAQUE、OraData、TIMESTAMPTZなど)のサポートのために用意されています。 |
oracle.sql.*データ型の一般的なサポート
各Oracleデータ型クラスは、特に次の機能をサポートします。
SQLデータ用のJavaバイト配列であるデータ記憶域。
JDBC仕様の定義に従って、データを対応するJavaクラスのオブジェクトに変換するtoJdbc()メソッド。
JDBCドライバは、BFILEなどの、JDBC仕様の一部ではないOracle固有のデータ型を変換しません。ドライバは、対応するoracle.sql.*形式でオブジェクトを戻します。
SQLデータをJava型に変換するのに適切なxxxValueメソッド。たとえば、stringValue、intValue、booleanValue、dateValueおよびbigDecimalValueがあげられます。
補足的な変換メソッド。データをストリームとして取り出すラージ・オブジェクト(LOB)クラスのメソッド、およびオブジェクト参照を使用してオブジェクト・データの取出しや設定を行うREFクラスのメソッドなど、データ型の機能に適したgetXXXおよびsetXXX。
oracle.sql.STRUCTクラスは、java.sql.StructインタフェースのOracle実装です。このクラスは値クラスです。構成後にクラスの内容を変更しないでください。このクラスは、すべてのoracle.sql.*データ型のクラスと同様に、oracle.sql.Datumクラスのサブクラスです。
JDK 1.5でSTRUCTオブジェクトを作成する場合、oracle.jdbc.OracleConnectionインタフェースのcreateStructメソッドを使用します。STRUCTオブジェクトを作成するためのこのファクトリ・メソッドのシグネチャは、次のとおりです。
Struct createStruct (String typeName, Object[] attributes) throws SQLException
JDK 1.6でSTRUCTオブジェクトを作成する場合、標準のjava.sql.createStructメソッドを使用できます。
oracle.sql.STRUCTを使用するのではなく、JDBC標準型、java.sql.StructおよびJDBC標準メソッドを使用する必要があります。コードを移植可能にする場合、Oracle JDBCドライバのみがoracle.sql.STRUCT型のインスタンスを使用するので、標準型を使用する必要があります。
|
注意: 可能なかぎり、コードではJDBC標準機能の使用を強くお薦めします。 |
|
関連項目: Oracle Database JDBC Java APIリファレンス |
クラスoracle.sql.REFの概要
oracle.sql.REFクラスは、Oracleオブジェクト参照をサポートする一般クラスです。このクラスは、すべてのoracle.sql.*データ型のクラスと同様に、oracle.sql.Datumクラスのサブクラスです。
REFクラスには、オブジェクト参照を取り出して渡すためのメソッドがあります。ただし、オブジェクト参照の選択によって取り出されるのは、オブジェクトへのポインタのみです。これによってオブジェクト自体がインスタンス化されることはありません。ただし、REFクラスにはオブジェクト・データを取り出して渡すためのメソッドも含まれています。JDBCアプリケーションではREFオブジェクトを作成できません。データベースから取り出すことができるのは、既存のREFオブジェクトのみです。
oracle.sql.REFを使用するのではなく、JDBC標準型、java.sql.RefおよびJDBC標準メソッドを使用する必要があります。コードを移植可能にする場合、Oracle JDBCドライバのみがoracle.sql.REF型のインスタンスを使用するので、標準型を使用する必要があります。
|
注意: 可能なかぎり、コードではJDBC標準機能の使用を強くお薦めします。 |
|
関連項目: Oracle Database JDBC Java APIリファレンス |
クラスoracle.sql.ARRAYの概要
oracle.sql.ARRAYクラスは、Oracleコレクション、つまりVARRAYまたはNESTED TABLEのいずれかをサポートします。データベースからVARRAYまたはNESTED TABLEを選択すると、JDBCドライバは、その内容をARRAYクラスのオブジェクトとしてインスタンス化します。データの構造は、いずれの場合も同じです。oracle.sql.ARRAYクラスは、oracle.sql.Datumを拡張して、標準JDBC 2.0 java.sql.Arrayインタフェースを実装します。
|
注意: oracle.sql.ARRAYを使用するのではなく、JDBC標準型、java.sql.ArrayおよびJDBC標準メソッドを使用する必要があります。コードを移植可能にする場合、Oracle JDBCドライバのみがoracle.sql.ARRAY型のインスタンスを使用するので、標準型を使用する必要があります。
可能なかぎり、コードではJDBC標準機能の使用を強くお薦めします。 |
OraclePreparedStatementインタフェースまたはOracleCallableStatementインタフェースのsetARRAYメソッドを使用すると、ARRAYをプリコンパイルされたSQL文への入力パラメータとして渡すことができます。同様に、OracleConnectionインタフェースのcreateARRAYメソッドを使用してARRAYオブジェクトを作成し、プリコンパイルされたSQL文またはコール可能文に渡し、データベースへの挿入などの操作を行う場合も考えられます。
クラスoracle.sql.BLOB、oracle.sql.CLOB、oracle.sql.BFILEの概要
バイナリ・ラージ・オブジェクト(BLOB)、キャラクタ・ラージ・オブジェクト(CLOB)およびバイナリ・ファイル(BFILE)は、大きすぎてデータベース表に直接格納できないデータ項目に使用します。一方、データベース表はデータの実際の場所を指すロケータを格納します。
|
注意:
|
oracle.sqlパッケージは、これらのデータ型を次のいくつかの方法でサポートします。
BLOBは、ラージ非構造化バイナリ・データ項目を指し、oracle.sql.BLOBクラスによりサポートされます。
CLOBは、ラージ文字データ項目を指し、oracle.sql.CLOBクラスによりサポートされます。
BFILEは、外部ファイル(オペレーティング・システム・ファイル)の内容を指し、oracle.sql.BFILEクラスによりサポートされます。BFILEは読取り専用です。
BLOB、CLOBまたはBFILEの各ロケータは、標準的なSELECT文を使用してデータベースから選択できます。ただし、受け取るのはデータではなく、ロケータのみです。データの取出しには、追加処理が必要です。
クラスoracle.sql.DATE、oracle.sql.NUMBERおよびoracle.sql.RAWの概要
これらのクラスは、プリミティブSQLデータ型を、Oracleネイティブの表現で保持します。ほとんどの場合、ドライバはこれらの型を内部的に使用しません。なるべく標準JDBC型を使用してください。
JavaのDoubleおよびFloat NaN値には等価のOracle NUMBER表現が存在しないため、Double.NaN値またはFloat.NaN値がoracle.sql.NUMBERクラスを使用してOracle NUMBERに変換されると、NullPointerExceptionが発生します。たとえば、次のコードにより、NullPointerExceptionが発生します。
oracle.sql.NUMBER n = new oracle.sql.NUMBER(Double.NaN); System.out.println(n.doubleValue()); // throws NullPointerException
クラスoracle.sql.TIMESTAMP、oracle.sql.TIMESTAMPTZおよびoracle.sql.TIMESTAMPLTZの概要
JDBCドライバでは、次のような日付/時刻データ型をサポートしています。
TIMESTAMP(TIMESTAMP)
TIMESTAMP WITH TIME ZONE(TIMESTAMPTZ)
TIMESTAMP WITH LOCAL TIME ZONE(TIMESTAMPLTZ)
JDBCドライバでは、DATEと日付/時刻データ型の間での変換が可能です。たとえば、DATE値としてTIMESTAMP WITH TIME ZONE列にアクセスできます。
JDBCドライバは、業界で最も一般的なタイムゾーン名と、JDKで定義されたタイムゾーン名をサポートしています。タイムゾーンは、java.util.TimeZoneクラスを使用して指定します。
|
注意:
|
次のコードは、JDKに定義されていないタイムゾーン名であるUS_PACIFICにTimeZoneオブジェクトとCalendarオブジェクトを作成する方法を示します。
TimeZone tz = TimeZone.getDefault();
tz.setID("US_PACIFIC");
GregorianCalendar gcal = new GregorianCalendar(tz);
次のJavaクラスは、SQL日付/時刻データ型を表します。
oracle.sql.TIMESTAMP
oracle.sql.TIMESTAMPLTZ
oracle.sql.TIMESTAMPLTZ
TIMESTAMP WITH LOCAL TIME ZONEデータにアクセスする前に、OracleConnection.setSessionTimeZone(String regionName)メソッドをコールして、セッション・タイム・ゾーンを設定します。このメソッドがコールされると、JDBCドライバは接続のセッション・タイム・ゾーンを設定、保存して、JDBCを介してアクセスされるTIMESTAMP WITH LOCAL TIME ZONEデータをセッション・タイム・ゾーンを使用して調整できるようにします。
|
注意: TIMESTAMP WITH TIME ZONE型とTIMESTAMP WITH LOCAL TIME ZONE型は、標準のjava.sql.Timestamp型として表せます。TIMESTAMP WITH TIME ZONE型とTIMESTAMP WITH LOCAL TIME ZONE型のjava.sql.Timestampに対するバイト表現は簡単です。これは、TIMESTAMP WITH TIME ZONEデータ型とTIMESTAMP WITH LOCAL TIME ZONEデータ型の内部形式はGMTで、java.sql.Timestamp型オブジェクトは内部では、エポックからのミリ秒数であるミリ秒時間値を使用するためです。ただし、これらのデータ型のString表現には、サーバーから動的に取得され、クライアント側にキャッシュされているタイム・ゾーン情報が必要です。
JDBCドライバの旧バージョンでは、タイム・ゾーンのキャッシュは様々な接続で共有されていました。このため、様々なタイム・ゾーンでの非互換性が原因で問題が発生することがよくありました。Oracle Database 11.2リリースのJDBCドライバから、タイム・ゾーン・キャッシュは、データベースが提供するタイム・ゾーンのバージョンを基礎とします。この新設計のキャッシュは、タイム・ゾーンのバージョン非互換性に関連するどのような問題も回避します。 |
クラスoracle.sql.OPAQUEの概要
oracle.sql.OPAQUEクラスは、OPAQUE型の名前と特性および任意の属性を提供します。OPAQUE型では、インスタンスの連続バイトにのみアクセスできます。
|
注意: OPAQUE型のサポートは限定されています。 |
oracle.jdbcパッケージのインタフェースは、java.sqlのインタフェースに対するOracle拡張機能を定義します。これらの拡張機能は、Oracle SQL形式データおよびOracle固有の他の機能(Oracleパフォーマンス拡張機能など)にアクセスできます。
Oracle文字データ型には、SQL CHARおよびNCHARデータ型が含まれます。次の各項では、oracle.sql.*クラスを使用してこれらのデータ型にアクセスする方法について説明します。
SQL CHARデータ型には、CHAR、VARCHAR2およびCLOBデータ型が含まれます。これらのデータ型を使用すると、文字データをデータベース・キャラクタ・セットのコード体系で格納できます。データベースのキャラクタ・セットは、データベースの作成時に決まります。
SQL NCHARデータ型は、グローバリゼーション・サポート用に作成されたものです。SQL NCHARデータ型には、NCHAR、NVARCHAR2およびNCLOBデータ型が含まれます。これらのデータ型を使用すると、UnicodeデータをデータベースNCHARキャラクタ・セットのコード体系で格納できます。NCHARキャラクタ・セットは、データベースの作成時に決まり、変更されることはありません。
|
注意: UnicodeStreamクラスが非推奨となってCharacterStreamクラスが導入されたため、NCHARデータ型でのアクセスではsetUnicodeStreamメソッドとgetUnicodeStreamメソッドはサポートされません。ストリーム・アクセスを使用する場合、setCharacterStreamメソッドとgetCharacterStreamメソッドを使用します。 |
SQL NCHARデータ型の使用方法は、SQL CHARデータ型の場合に類似しています。JDBCでは、対応するSQL CHARデータ型で使用されるのと同じクラスおよびメソッドを使用して、SQL NCHARデータ型にアクセスします。したがって、oracle.sqlパッケージには、SQL NCHARデータ型用の対応する別のクラスが定義されていません。同様に、SQL NCHARデータ型用のoracle.jdbc.OracleTypesクラスにも、対応する別の定数は定義されていません。
|
注意: JDK 1.5の場合、JDBCプログラムは、特に各国語文字を必要とするこれらの列のためにsetFormOfUseメソッドをコールする必要があります。 |
次のコードは、SQL NCHARデータにアクセスする方法を示します。
//
// Table TEST has the following columns:
// - NUMBER
// - NVARCHAR2
// - NCHAR
//
oracle.jdbc.OraclePreparedStatement pstmt =
(oracle.jdbc.OraclePreparedStatement)
conn.prepareStatement("insert into TEST values(?, ?, ?)");
//
// oracle.jdbc.OraclePreparedStatement.FORM_NCHAR should be used for all NCHAR,
// NVARCHAR2 and NCLOB data types.
//
pstmt.setInt(1, 1); // NUMBER column
pstmt.setNString(2, myUnicodeString1); // NVARCHAR2 column
pstmt.setNString(3, myUnicodeString2); // NCHAR column
pstmt.execute();
oracle.sql.CHARクラスは、文字データを処理および変換するためにOracle JDBCによって使用されます。このクラスは、文字データを変換するためのグローバリゼーション・サポート機能を提供します。このクラスには、グローバリゼーション・サポート・キャラクタ・セットおよび文字データという2つの主要な属性があります。グローバリゼーション・サポート・キャラクタ・セットは、文字データのエンコーディングを定義します。これは、CHARオブジェクトの作成時に必ず渡されるパラメータです。グローバリゼーション・サポート・キャラクタ・セット情報がない状態では、CHARオブジェクト内のデータ・バイトは無意味です。oracle.sql.CHARクラスは、SQL CHARおよびSQL NCHARの両方のデータ型に使用されます。
|
注意: 10g リリース1(10.1)より前のバージョンのOracle JDBCドライバでは、oracle.SQL.CHARを使用することでパフォーマンス上の利点がありました。Oracle Database 10g以上では、このような利点はありません。実際には、java.lang.Stringを使用することで最適なパフォーマンスを実現できます。すべてのOracle JDBCドライバが、Java UCS2キャラクタ・セット内のすべての文字データを処理します。oracle.sql.CHARを使用すると、データベース・キャラクタ・セットとUCS2キャラクタ・セットとの間の変換が発生します。 |
oracle.sql.CHARクラスに残された唯一の使用方法は、文字データをOracleグローバリゼーション・サポート・キャラクタ・セットでエンコードされたRAWバイトの形式で処理する場合です。Oracle Databaseから取り出された文字データはすべてjava.lang.Stringクラスを使用してアクセスしてください。別のソースからのバイト・データを処理する場合は、oracle.sql.CHARを使用してバイトをjava.lang.Stringに変換できます。
oracle.sql.CHARを変換するには、データ・バイトと、そのデータ・バイトのエンコードに使用するグローバリゼーション・サポート・キャラクタ・セットを示すoracle.sql.CharacterSetインスタンスを用意する必要があります。
Oracleオブジェクト属性であるCHARオブジェクトは、データベース・キャラクタ・セットで戻されます。
CHARオブジェクトは、必要に応じてJDBCドライバで自動的に作成されるため、まれに作成する必要がある場合でも、JDBCアプリケーション・コードでCHARオブジェクトを直接作成する必要はほとんどありません。
CHARオブジェクトを作成する場合は、CharacterSetクラスのインスタンスによって、CHARオブジェクトにキャラクタ・セット情報を提供する必要があります。このクラスの各インスタンスは、Oracleがサポートしているグローバリゼーション・サポート・キャラクタ・セットの1つを表します。CharacterSetインスタンスは、キャラクタ・セットのメソッドおよび属性をカプセル化し、主に他のキャラクタ・セットとの相互変換機能を提供します。
oracle.sql.CHARオブジェクトの作成
CHARオブジェクトを構築する際、次の一般的な手順に従ってください。
CharacterSetオブジェクトは、static CharacterSet.makeメソッドをコールして作成します。
このメソッドは、キャラクタ・セット・インスタンスのファクトリです。makeメソッドは、Oracleがサポートするキャラクタ・セットIDに対応する整数を入力として取ります。たとえば、次のようになります。
int oracleId = CharacterSet.JA16SJIS_CHARSET; // this is character set ID,
// 832
...
CharacterSet mycharset = CharacterSet.make(oracleId);
Oracleがサポートする各キャラクタ・セットは、事前定義済の一意なOracle IDを保持します。
CHARオブジェクトを作成します。
文字列または文字列を表すバイトを、キャラクタ・セットに基づくバイトの解釈方法を指定するCharacterSetオブジェクトとともに、コンストラクタに渡します。たとえば、次のようになります。
String mystring = "teststring"; ... CHAR mychar = new CHAR(teststring, mycharset);
CHARには、CharacterSetオブジェクトとともに、String、byte配列またはオブジェクトを入力として使用できる複数のコンストラクタがあります。Stringの場合、文字列は、CharacterSetオブジェクトが示すキャラクタ・セットに変換されてから、CHARオブジェクトに格納されます。
oracle.sql.CHAR Conversionメソッド
CHARクラスは、文字データを文字列に変換するための次のようなメソッドを提供します。
このメソッドは、CHARオブジェクトによって表された文字のシーケンスを文字列に変換し、Java Stringオブジェクトを戻します。無効なOracleIDを入力した場合、キャラクタ・セットは認識されず、getStringメソッドはSQLException例外をスローします。
このメソッドはgetStringメソッドと同じです。ただし、無効なOracleIDを入力すると、キャラクタ・セットが認識されず、toStringメソッドによりCHARデータの16進表現が戻されます。SQLException例外はスローされません。
このメソッドはgetStringメソッドと同一ですが、CHARオブジェクトのキャラクタ・セットにUnicode表現のない文字が、デフォルトの置換文字で置き換えられる点が異なります。デフォルトの置換文字はキャラクタ・セットによって異なりますが、多くの場合は疑問符(?)です。
データベース・サーバーとクライアント、またはクライアント上で動作するアプリケーションでは、異なるキャラクタ・セットを使用できます。CHARクラスのメソッドを使用してデータをサーバーとクライアント間で転送する場合、JDBCドライバはデータをサーバーのキャラクタ・セットからクライアントのキャラクタ・セットに(またはその逆に)変換する必要があります。データを変換する際、ドライバはグローバリゼーション・サポートを使用します。
Oracle JDBCドライバは、Oracle固有のBFILEデータ型、ROWIDデータ型およびREF CURSOR型をサポートしますが、これらは標準JDBC仕様に含まれていません。このセクションでは、ROWIDおよびREF CURSOR型の拡張について説明します。ROWIDはJava文字列としてサポートされ、REF CURSOR型はJDBC結果セットとしてサポートされます。
この項の内容は次のとおりです。
ROWIDは、Oracle Database表の行ごとに一意の識別タグです。ROWIDは、各行のIDを含む仮想列とみなすこともできます。
oracle.sql.ROWIDクラスは、ROWID SQLデータ型のコンテナとして提供されます。
ROWIDは、java.sql.ResultSetインタフェースで指定されるgetCursorNameメソッドおよびjava.sql.Statementインタフェースで指定されるsetCursorNameメソッドに類似した機能を提供します。
問合せにROWID擬似列を指定した場合は、結果セットgetStringメソッドを使用してROWIDを取得できます。また、setStringメソッドを使用すると、ROWIDにPreparedStatementパラメータをバインドできます。これによって、次の例に示すように、埋込み更新を実行できます。
|
注意: oracle.sql.ROWIDクラスを使用するのは、J2SE 1.5を使用する場合のみとしてください。JSE 6の場合は、標準のjava.sql.RowIdインタフェースを使用してください。 |
例
次の例では、ROWIDデータに対するアクセスおよび操作の方法を示します。
|
注意: 次の例は、JSE 6でのみ動作します。 |
Statement stmt = conn.createStatement();
// Query the employee names with "FOR UPDATE" to lock the rows.
// Select the ROWID to identify the rows to be updated.
ResultSet rset =
stmt.executeQuery ("SELECT ename, rowid FROM emp FOR UPDATE");
// Prepare a statement to update the ENAME column at a given ROWID
PreparedStatement pstmt =
conn.prepareStatement ("UPDATE emp SET ename = ? WHERE rowid = ?");
// Loop through the results of the query
while (rset.next ())
{
String ename = rset.getString (1);
RowId rowid = rset.getROWID(2); // Get the ROWID as a String
pstmt.setString (1, ename.toLowerCase ());
pstmt.setROWID (2, rowid); // Pass ROWID to the update statement
pstmt.executeUpdate (); // Do the update
}
カーソル変数は、問合せ作業領域の(内容でなく)メモリーの場所を保持します。カーソル変数を宣言すると、ポインタが作成されます。SQLでは、ポインタはデータ型REF xを取ります。ここで、REFはREFERENCEの省略形で、xは参照されるエンティティを表します。したがって、REF CURSORはカーソル変数への参照を表します。多くの作業領域を参照する多くのカーソル変数が存在する可能性があるため、REF CURSORは、異なる多くの型のカーソル変数を識別するカテゴリまたはデータ型指定子と考えることができます。
|
注意: REF CURSORインスタンスはスクロール可能ではありません。 |
カーソル変数を作成するには、まずREF CURSORカテゴリに属する型を識別します。たとえば、次のようになります。
DECLARE TYPE DeptCursorTyp IS REF CURSOR
次に、カーソル変数をDeptCursorTyp型と宣言することによって、カーソル変数を作成します。
dept_cv DeptCursorTyp - - declare cursor variable ...
REF CURSORは、特定のデータ型ではなく、データ型のカテゴリです。
ストアド・プロシージャにより、REF CURSORカテゴリのカーソル変数が戻されます。この出力は、データベース・カーソルまたはJDBC結果セットと等価です。REF CURSORには、基本的に問合せの結果が格納されます。
JDBCでは、REF CURSORは、ResultSetオブジェクトとしてインスタンス化され、次の方法でアクセスできます。
ストアド・プロシージャをコールするにはJDBCコール可能文を使用します。出力パラメータがあるため、プリコンパイルされたSQL文ではなく、コール可能文を使用する必要があります。
ストアド・プロシージャによってREF CURSORが戻されます。
Javaアプリケーションによってコール可能文がOracleコール可能文にキャストされ、OracleCallableStatementクラスのgetCursorメソッドを使用してREF CURSORがJDBC ResultSetオブジェクトとしてインスタンス化されます。
結果セットは要求どおりに処理されます。
|
重要: REF CURSORと関連付けられたカーソルは、そのREF CURSORを作成したStatementオブジェクトがクローズされるたびにクローズされます。
過去のリリースとは異なり、 |
例
この例では、REF CURSORデータにアクセスする方法を示します。
import oracle.jdbc.*;
...
CallableStatement cstmt;
ResultSet cursor;
// Use a PL/SQL block to open the cursor
cstmt = conn.prepareCall
("begin open ? for select ename from emp; end;");
cstmt.registerOutParameter(1, OracleTypes.CURSOR);
cstmt.execute();
cursor = ((OracleCallableStatement)cstmt).getCursor(1);
// Use the cursor like a standard ResultSet
while (cursor.next ())
{System.out.println (cursor.getString(1));}
この例について、説明します。
CallableStatementオブジェクトは、接続クラスのprepareCallメソッドを使用して作成されます。
コール可能文によって、REF CURSORを戻すPL/SQLプロシージャが実装されます。
コール可能文の出力パラメータは、通常どおり登録してその型を定義する必要があります。REF CURSORには、型コードOracleTypes.CURSORを使用します。
コール可能文が実行され、REF CURSORが戻されます。
標準JDBC APIのOracle拡張機能getCursorメソッドを使用するため、CallableStatementオブジェクトをOracleCallableStatementにキャストします。REF CURSORがResultSetオブジェクトに戻されます。
Oracle BINARY_FLOAT型およびBINARY_DOUBLE型は、IEEE 574のfloat型とdouble型のデータを格納するために使用します。これらの型は、負とゼロおよびNaNを除いて、Javaのfloatスカラー型とdoubleスカラー型に相当します。
|
関連項目: Oracle Database SQL言語リファレンス |
BINARY_DOUBLE列を問合せに含めると、データはデータベースからバイナリ形式で取り出されます。getDoubleメソッドも、データをバイナリ形式で戻します。一方、NUMBERデータ型の列の場合は、数値ビットが戻り、Javaのdoubleデータ型に変換されます。
|
注意: SQLFLOAT型、DOUBLE PRECISION型およびREALデータ型のOracle表現は、Oracle NUMBER表現を使用します。BINARY_FLOAT型とBINARY_DOUBLEデータ型は、独自の型とみなされます。 |
PreparedStatementインタフェースのJDBC標準setDouble(int, double)メソッドのコールは、Javaのdouble引数をOracleのNUMBERスタイル・ビットに変換してからデータベースに送信します。一方、oracle.jdbc.OraclePreparedStatementインタフェースのsetBinaryDouble(int, double)メソッドは、データを内部バイナリ・ビットに変換してからデータベースに送信します。
使用するデータ形式が、PreparedStatementインタフェースのターゲット・パラメータの型と一致していることを確認してください。この確認によって、データの正確性が保持され、CPUの使用も最小限に抑えられます。NUMBERパラメータにsetBinaryDoubleを使用すると、バイナリ・ビットはサーバーに送信され、NUMBER形式に変換されます。データの正確性は保持されますが、サーバーのCPU負荷は増加します。BINARY_DOUBLEパラメータにsetDoubleを使用すると、データは、クライアントでNUMBERビットに変換されてからサーバーに送信され、そこでバイナリ形式に再変換されます。この方法では、クライアントとサーバーの両方でCPU負荷が増大し、データの精度も低下する可能性があります。
SetFloatAndDoubleUseBinary接続プロパティがtrueに設定されていると、JDBC標準API、setFloat(int, float)、setDouble(int, double)、およびすべての変数では、NUBMERビットではなく、内部バイナリ・ビットを送信するようになります。
|
注意: ここでは、主にBINARY_DOUBLEについて説明しましたが、BINARY_FLOATについても同じ内容が適用されます。 |
Oracle Database 11gリリース2(11.2)では、SYS.ANYTYPEおよびSYS.ANYDATAというOracle型にアクセスするためのJavaインタフェースがサポートされています。
|
関連項目: これらのOracle型の詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。 |
SYS.ANYTPE型のインスタンスには、オブジェクト型およびコレクション型も含め、SQL型の型記述(永続か一時、名前付きか名前なし)が含まれます。oracle.sql.TypeDescriptorクラスを使用すると、SYS.ANYTYPE型にアクセスできます。ANYTYPEインスタンスは、PL/SQLのプロシージャまたはSQLのSELECT文(SYS.ANYTYPEを列型として使用)を使用して取り出すことができます。ANYTYPEインスタンスをデータベースから取り出すには、getObjectメソッドを使用します。このメソッドは、TypeDescriptorのインスタンスを戻します。
次の任意のANYTYPEインスタンスを取り出すことができます。
一時オブジェクト型
一時事前定義済型
永続オブジェクト型
永続事前定義済型
例4-1 SYS.ANYTYPE型へのアクセス
次のコードは、ANYTYPEのインスタンスをデータベースから取り出す方法を示しています。
...
ResultSet rs = stmt.executeQuery("select anytype_column from my_table");
TypeDescriptor td = (TypeDescriptor)rs.getObject(1);
short typeCode = td.getInternalTypeCode();
if(typeCode == TypeDescriptor.TYPECODE_OBJECT)
{
// check if it's a transient type
if(td.isTransientType())
{
AttributeDescriptor[] attributes = ((StructDescriptor)td).getAttributesDescriptor();
for(int i=0; i<attributes.length; i++)
System.out.println(attributes[i].getAttributeName());
}
else
{ System.out.println(td.getTypeName()); }}
...
例4-2 一時オブジェクト型のPL/SQLによる作成とJDBCによる取出し
次のサンプル・コードは、JDBCによる一時オブジェクト型の取出し方法を示しています。
...
OracleCallableStatement cstmt = (OracleCallableStatement)conn.prepareCall
("BEGIN ? := transient_obj_type (); END;");
cstmt.registerOutParameter(1,OracleTypes.OPAQUE,"SYS.ANYTYPE");
cstmt.execute();
TypeDescriptor obj = (TypeDescriptor)cstmt.getObject(1);
if(!obj.isTransient())
System.out.println("This must be a JDBC bug");
cstmt.close();
return obj;
...
例4-3 ANYTYPEをINパラメータとして受け取るPL/SQLストアド・プロシージャのコール
次のコードは、ANYTYPEをINパラメータとして受け取るPL/SQLストアド・プロシージャのコール方法を示しています。
...
CallableStatement cstmt = conn.prepareCall("BEGIN ? := dumpanytype(?); END;");
cstmt.registerOutParameter(1,OracleTypes.VARCHAR);
// obj is the instance of TypeDescriptor that you have retrieved
cstmt.setObject(2,obj);
cstmt.execute();
String str = (String)cstmt.getObject(1);
...
oracle.sql.ANYDATAクラスを使用すると、データベースからSYS.ANYDATAインスタンスにアクセスできます。このクラスのインスタンスは、oracle.sql.Datumの任意の有効なインスタンスから取得できます。convertDatumファクトリ・メソッドは、Datumのインスタンスを受け取り、ANYDATAのインスタンスを戻します。このファクトリ・メソッドの構文は、次のとおりです。
public static ANYDATA convertDatum(Datum datum) throws SQLException
oracle.sql.ANYDATAのインスタンスを作成するためのサンプル・コードを、次に示します。
// struct is a valid instance of oracle.sql.STRUCT that either comes from the // database or has been constructed in Java. ANYDATA myAnyData = ANYDATA.convertDatum(struct);
例4-4 ANYDATAのインスタンスに対するデータベースからのアクセス
...
// anydata_table has been created as:
// CREATE TABLE anydata_tab (data SYS.ANYDATA)
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select data from my_anydata_tab");
while(rs.next())
{
ANYDATA anydata = (ANYDATA)rs.getObject(1);
if(!anydata.isNull())
{
TypeDescriptor td = anydata.getTypeDescriptor();
if(td.getTypeCode() == OracleType.TYPECODE_OBJECT)
STRUCT struct = (STRUCT)anydata.accessDatum();
}
}
...
例4-5 データベース表へのANYDATAとしてのオブジェクトの挿入
表およびオブジェクト型が次のように定義されているものとします。
CREATE TABLE anydata_tab ( id NUMBER, data SYS.ANYDATA) CREATE OR REPLACE TYPE employee AS OBJECT ( empno NUMBER, ename VARCHAR2(10) )
SQLオブジェクト型EMPLOYEEのインスタンスを作成し、それをanydata_tabに挿入するには、次のようなコードを記述します。
...
PreparedStatement pstmt = conn.prepareStatement("insert into anydata_table values (?,?)");
StructDescriptor sd = StructDescriptor.createDescriptor("EMPLOYEE",(OracleConnection)conn);
Object[] objattr = new Object[2];
objattr[0] = new BigDecimal(1120);
objattr[1] = new String("Papageno");
STRUCT myEmployeeStr = new STRUCT(sd,conn,objattr);
ANYDATA anyda = ANYDATA.convertDatum(myEmployeeStr);
pstmt.setInt(1,123);
pstmt.setObject(2,anyda);
pstmt.executeUpdate();
...
oracle.jdbcパッケージのインタフェースは、java.sqlのインタフェースに対するOracle拡張機能を定義します。これらの拡張機能によって、この章に記載されているSQL形式のデータへのアクセスが可能になります。また、Oracleパフォーマンス拡張要素など、Oracle固有の他の機能へのアクセスも可能になります。
表4-1に、oracle.jdbcパッケージに含まれる接続に使用する主なインタフェースとクラス、文および結果セットのリストを示します。
表4-1 oracle.jdbcパッケージの主なインタフェースおよびクラス
| 名前 | インタフェースまたはクラス | 主要機能 |
|---|---|---|
|
|
クラス |
|
|
|
インタフェース |
Oracle Databaseインスタンスを起動または停止するためのメソッド、Oracle Statementオブジェクトを戻すメソッド、および現行接続で実行される任意の文に対応したOracleパフォーマンス拡張機能を設定するメソッドを提供します。
|
|
|
インタフェース |
文ごとにOracleパフォーマンス拡張機能を設定するメソッドを提供します。
|
|
|
インタフェース |
SELECT文を実行しないでプリコンパイルされたSQL文からメタデータを取得する
|
|
|
インタフェース |
データを
|
|
|
インタフェース |
|
|
|
インタフェース |
列名やデータ型などのOracle結果セットのメタデータ情報を取得するメソッドを提供します。
|
|
|
クラス |
データベース製品名/バージョン、表情報、デフォルト・トランザクション分離レベルなどのデータベースに関するメタデータ情報を取得するメソッドを提供します。
|
|
|
クラス |
SQL型を識別する整数定数を定義します。 標準型の場合、同じ値を標準 |
この項の内容は次のとおりです。
このインタフェースは、標準JDBC接続機能を拡張して、Oracle Statementオブジェクトの作成と取得、Oracleパフォーマンス拡張機能用のフラグやオプションの設定、Oracleオブジェクト用型マップのサポート、およびクライアント識別子のサポートを実施します。
Oracle Database 11gリリース1(11.1)では、Oracle Databaseインスタンスの起動と停止を実行できる新しいメソッドがこのインタフェースに追加されていました。また、OracleConnectionインタフェースでは、可視性および透明性を向上させるために、すべての接続プロパティを定数として定義します。
このインタフェースは、DATEおよびNUMBERのようなoracle.sqlデータ値を構築するために、ファクトリ・メソッドも定義します。ファクトリ・メソッドの使用時には次の点に注意してください。
oracle.sql型のインスタンスを構築するすべてのコードで、Oracle拡張ファクトリ・メソッドを使用する必要があります。たとえば、ARRAY、BFILE、DATE、INTERVALDS、NUMBER、STRUCT、TIME、TIMESTAMPなどです。
標準型のインスタンスを構築するすべてのコードで、JDBC4.0標準ファクトリ・メソッドを使用する必要があります。たとえば、CLOBBLOBNCLOBなどです。
CHAR、JAVA_STRUCT、ArrayDescriptorおよびStructDescriptorにはファクトリ・メソッドがありません。これらの型は内部ドライバの使用のためのみに用意されています。
|
注意: Oracle Database 11gリリース1(11.1)より前では、引数としてARRAYおよびSTRUCTクラス・コンストラクタに渡すために、ArrayDescriptorsおよびStructDescriptorsを作成する必要がありました。新しいARRAYおよびStructファクトリ・メソッドは記述子の引数がありません。ドライバはまだ内部で記述子を使用していますが、作成する必要はありません。 |
クライアント識別子
クライアント識別子を接続プーリング環境で使用すると、データベース・セッションを現在使用している軽量ユーザーを識別できます。クライアント識別子を使用すると、異なるデータベース・セッション間でグローバル・アクセス・アプリケーション・コンテキストを共有することもできます。データベース・セッションで設定されたクライアント識別子は、データベース監査がオンにされたときに監査されます。
|
関連項目: 『Oracle Databaseアドバンスト・アプリケーション開発者ガイド』および『Oracle Database JDBC Java APIリファレンス』 |
このインタフェースは標準のJDBC文機能を拡張するもので、OraclePreparedStatementクラスとOracleCallableStatementクラスのスーパーインタフェースです。拡張された機能には、Oracleパフォーマンス拡張機能用の設定フラグとオプションの文単位でのサポートが含まれます。OracleConnectionインタフェースでは、それらを接続単位で設定していました。
このインタフェースは、OracleStatementインタフェースを拡張し、標準JDBCのプリコンパイルされたSQL文の機能を拡張します。また、oracle.jdbc.OraclePreparedStatementインタフェースはOracleCallableStatementインタフェースによって拡張されます。拡張機能は次の機能から構成されます。
oracle.sql.*型とオブジェクトをプリコンパイルされたSQL文にバインドするためのsetXXXメソッド
SELECT文を実行しないで、プリコンパイルされたSQL文からメタデータを取得するためのgetMetaDataメソッド
文単位でOracleパフォーマンス拡張機能をサポートするためのメソッド
|
注意: :NEWまたは:OLD列を参照するトリガーの作成にPreparedStatementインタフェースを使用しないでください。かわりに、Statementを使用してください。PreparedStatementを使用すると、実行が失敗し、メッセージ「java.sql.SQLException: INまたはOUTパラメータがありません - 索引:: 1」が発行されます。 |
このインタフェースは、OracleStatementインタフェースを拡張するOraclePreparedStatementインタフェースを機能拡張し、標準JDBCのコール可能文機能を組み込みます。
|
注意: :NEWまたは:OLD列を参照するトリガーの作成にCallableStatementインタフェースを使用しないでください。かわりにStatementを使用してください。CallableStatementを使用すると、実行が失敗し、メッセージ「java.sql.SQLException: INまたはOUTパラメータがありません - 索引:: 1」が発行されます。 |
|
注意:
|
このインタフェースは、標準JDBC結果セットの機能を拡張し、getXXXメソッドを実装してデータをoracle.sql.*オブジェクト内に取得します。
このインタフェースは、標準JDBC結果セットのメタデータ機能を拡張して、Oracle結果セット・オブジェクトの情報を取得します。
OracleTypesクラスは、JDBCがSQL型を識別するのに使用する定数を定義します。このクラス内の各変数は、整数の定数値を持ちます。oracle.jdbc.OracleTypesクラスには、標準Java java.sql.Typesクラスの型コード定義の複製と、次のOracle拡張機能用の補足的な型コードが含まれます。
OracleTypes.BFILE
OracleTypes.ROWID
OracleTypes.CURSOR(REF CURSOR型の場合)
OracleTypes.CHAR_BYTES(同じ列のsetNullとsetCHARメソッドをコールする場合)
java.sql.Typesの場合と同様に、変数名はすべて大文字にする必要があります。
JDBCは、OracleTypesクラスの要素によって識別されたSQL型を、出力パラメータの登録、およびPreparedStatementクラスのsetNullメソッドという2つの分野で使用します。
OracleTypesと出力パラメータの登録
java.sql.Typesまたはoracle.jdbc.OracleTypesの型コードは、java.sql.CallableStatementインタフェースおよびoracle.jdbc.OracleCallableStatementインタフェースのregisterOutParameterメソッドで出力パラメータのSQL型を識別します。
次に、CallableStatementインタフェースおよびOracleCallableStatementインタフェースでregisterOutputParameterメソッドが使用可能な形式を示します。
cs.registerOutParameter(int index, int sqlType); cs.registerOutParameter(int index, int sqlType, String sql_name); cs.registerOutParameter(int index, int sqlType, int scale);
これらのシグネチャでは、indexにはパラメータ索引が、sqlTypeにはSQLデータ型の型コードが入ります。sql_nameにはデータ型に与えられた名前が入りますが、sqlTypeがSTRUCT、REFまたはARRAY型コードの場合にはユーザー定義型の名前が入ります。さらに、sqlTypeがNUMERICまたはDECIMAL型コードの場合には、scaleに、小数点の右側にある桁の数が入ります。
次の例は、CallableStatementインタフェースを使用して、charoutという名前付きプロシージャをコールしています。CHARデータ型が戻されます。registerOutParameterメソッドにおけるOracleTypes.CHAR型のコードの使用に注意してください。
CallableStatement cs = conn.prepareCall ("BEGIN charout (?); END;");
cs.registerOutParameter (1, OracleTypes.CHAR);
cs.execute ();
System.out.println ("Out argument is: " + cs.getString (1));
次の例は、CallableStatementインタフェースを使用して、structoutをコールしています。STRUCTデータ型が戻されます。registerOutParameterの形式では、型コードにTypes.STRUCTまたはOracleTypes.STRUCT、SQL名にEMPLOYEEを指定する必要があります。
この例では、EMPLOYEE型でいかなる型マップも宣言されていないことを前提としているため、STRUCTデータ型内に取得されます。oracle.sql.STRUCTオブジェクトとしてEMPLOYEEの値を取り出すために、Statemenオブジェクトcsは、OracleCallableStatementにキャストされ、Oracle拡張機能getSTRUCTメソッドが実行されます。
CallableStatement cs = conn.prepareCall ("BEGIN structout (?); END;");
cs.registerOutParameter (1, OracleTypes.STRUCT, "EMPLOYEE");
cs.execute ();
// get the value into a STRUCT because it
// is assumed that no type map has been defined
STRUCT emp = ((OracleCallableStatement)cs).getSTRUCT (1);
OracleTypesおよびsetNullメソッド
TypesおよびOracleTypesでの型コードは、データ項目のSQL型を特定します。setNullメソッドがそれをNULLに設定します。setNullメソッドは、java.sql.PreparedStatementインタフェースとoracle.jdbc.OraclePreparedStatementインタフェースにあります。
次に、PreparedStatementおよびOraclePreparedStatementオブジェクトでsetNullメソッドが使用可能な形式を示します。
ps.setNull(int index, int sqlType); ps.setNull(int index, int sqlType, String sql_name);
これらのシグネチャでは、indexがパラメータ索引を表します。sqlTypeはSQLデータ型のための型コードです。sql_nameは、sqlTypeがSTRUCT、REFまたはARRAY型コードである場合に、ユーザー定義のデータ型に対して指定される名前です。無効なsqlTypeを入力すると、ParameterTypeConflict例外がスローされます。
次の例では、プリコンパイルされたSQL文を使用してNULL値をデータベースに挿入します。NULLに設定する数値オブジェクトの識別にはOracleTypes.NUMERICを使用することに注意してください。ただし、Types.NUMERICも使用されることがあります。
PreparedStatement pstmt =
conn.prepareStatement ("INSERT INTO num_table VALUES (?)");
pstmt.setNull (1, OracleTypes.NUMERIC);
pstmt.execute ();
この例では、プリコンパイルされたSQL文を使用して、EMPLOYEE型のNULL STRUCTオブジェクトをデータベースに挿入します。
PreparedStatement pstmt = conn.prepareStatement
("INSERT INTO employee_table VALUES (?)");
pstmt.setNull (1, OracleTypes.STRUCT, "EMPLOYEE");
pstmt.execute ();
同じ列のsetCHARメソッドもコールする場合、OracleTypes.CHAR_BYTES型をsetNullメソッドで使用することもできます。たとえば、次のようになります。
ps.setCHAR(n, aCHAR); ps.addBatch(); ps.setNull(n, OracleTypes.CHAR_BYTES); ps.addBatch();
この例では、OracleTypes.CHAR_BYTES型以外のどの型を使用しても、データベースとの余計なラウンドトリップが発生します。また、setNullメソッドを使用しないでコードを記述することもできます。たとえば、次の例のようにコードを記述することもできます。
ps.setCHAR(n, null);
oracle.sql.*クラスのgetJavaSqlConnectionメソッドはjava.sql.Connectionを戻します。このメソッドは、次のOracleデータ型クラスで使用できます。
|
注意: Oracle 8iおよびJDBCの以前のバージョンで使用されていたgetConnectionメソッドはoracle.jdbc.driver.OracleConnectionを戻します。Oracle 9iリリースのoracle.jdbcパッケージを優先して、oracle.jdbc.driverパッケージでのクラスの使用は非推奨になりました。Oracle Database 11gリリース1(11.1)から、パッケージoracle.jdbc.driverのクラスがサポート対象外になりました。 |
oracle.sql.ARRAY
oracle.sql.BFILE
oracle.sql.BLOB
oracle.sql.CLOB
oracle.sql.OPAQUE
oracle.sql.REF
oracle.sql.STRUCT
次のコードは、ArrayクラスのgetJavaSqlConnectionメソッドを示しています。
public class ARRAY
{
java.sql.Connection getJavaSqlConnection()
throws SQLException;
...
}
DML RETURNING機能は、自動生成キーの取出しに比べて、より豊富な機能を提供します。この機能は、自動生成キーの取出しに使用できますが、アプリケーションで使用する可能性がある他の列や値の取出しにも使用できます。
|
注意:
|
次の各項では、DML RETURNING機能のサポートについて説明します。
OraclePreparedStatementインタフェースは、DML RETURNINGをサポートするOracle固有のApplication Program Interface(API)に伴って機能拡張されました。DML RETURNINGによって戻されるパラメータおよび取り出されるデータを登録するために、registerReturnParameterメソッドおよびgetReturnResultSetメソッドがoracle.jdbc.OraclePreparedStatementインタフェースに追加されています。
DML RETURNING機能の戻りパラメータは、registerReturnParameterメソッドを使用して登録します。エラーが発生した場合、メソッドはSQLExceptionインスタンスをスローします。戻りパラメータの索引を指定する正の整数を渡す必要があります。また、戻りパラメータの型も指定する必要があります。戻りパラメータの最大バイト数または最大文字数も指定できます。このメソッドは、charまたはRAW型でのみ使用できます。SQL構造型の完全修飾名も指定できます。
|
注意: 戻りパラメータの最大サイズが不明な場合は、デフォルトの最大サイズを選択するregisterReturnParameter(int paramIndex, int externalType)を使用してください。戻りパラメータの最大サイズが判明している場合は、registerReturnParameter(int paramIndex, int externalType, int maxSize)を使用することでメモリー消費を抑制できます。 |
getReturnResultSetメソッドは、DML RETURNING機能で戻されたデータをフェッチし、ResultSetオブジェクトとして戻します。エラーが検出された場合は、SQLException例外が発生します。
|
注意: DML RETURNING機能のためのOracle固有のAPIは、Java Development Kit(JDK)1.5の場合はojdbc5.jar、JDK 1.6の場合はojdbc6.jarに含まれています。 |
DML RETURNING文を実行する前に、JDBCアプリケーションが、registerReturnParameterメソッドを1つ以上コールする必要があります。これらのメソッドは、戻りパラメータに関する型やサイズなどの情報をJDBCドライバに提供します。DML RETURNING文は、executeUpdateまたはexecuteのいずれかの標準JDBC APIを使用して処理されます。戻されたパラメータは、oracle.jdbc.OraclePreparedStatementインタフェースのgetReturnResultSetメソッドを使用して、ResultSetオブジェクトとしてフェッチできます。
ResultSetオブジェクトの値を読み取るには、基礎となるStatementオブジェクトをオープンする必要があります。基礎となるStatementオブジェクトがクローズされている場合は、戻されたResultSetオブジェクトもクローズ状態となります。この状態は、SQL問合せ文を処理することで取り出されたResultSetオブジェクトの状態と一致します。
DML RETURNING文を実行する場合、getReturnResultSetメソッドで戻されるResultSetオブジェクトの同時実行性はCONCUR_READ_ONLYであり、そのResultSetオブジェクト型はTYPE_FORWARD_ONLYまたはTYPE_SCROLL_INSENSITIVEである必要があります。
ここでは、DML RETURNING機能に関する2つのコード例を示します。
次のコードは、DML RETURNING機能の使用例です。この例では、name列の最大サイズを100文字と仮定します。name列の最大サイズが判明しているため、registerReturnParameter(int paramIndex, int externalType, int maxSize)メソッドを使用します。
...
OraclePreparedStatement pstmt = (OraclePreparedStatement)conn.prepareStatement(
"delete from tab1 where age < ? returning name into ?");
pstmt.setInt(1,18);
/** register returned parameter
* in this case the maximum size of name is 100 chars
*/
pstmt.registerReturnParameter(2, OracleTypes.VARCHAR, 100);
// process the DML returning statement
count = pstmt.executeUpdate();
if (count>0)
{
ResultSet rset = pstmt.getReturnResultSet(); //rest is not null and not empty
while(rset.next())
{
String name = rset.getString(1);
...
}
}
...
次のコードも、DML RETURNING機能の使用例です。ただし、この例では、戻りパラメータの最大サイズが不明です。したがって、registerReturnParameter(int paramIndex, int externalType)メソッドを使用します。
...
OraclePreparedStatement pstmt = (OraclePreparedStatement)conn.prepareStatement(
"insert into lobtab values (100, empty_clob()) returning col1, col2 into ?, ?");
// register return parameters
pstmt.registerReturnParameter(1, OracleTypes.INTEGER);
pstmt.registerReturnParameter(2, OracleTypes.CLOB);
// process the DML returning SQL statement
pstmt.executeUpdate();
ResultSet rset = pstmt.getReturnResultSet();
int r;
CLOB clob;
if (rset.next())
{
r = rset.getInt(1);
System.out.println(r);
clob = (CLOB)rset.getClob(2);
...
}
...
DML RETURNING機能を使用する場合は、次の点に注意してください。
getReturnResultSetメソッドを複数回起動した場合は、その戻り値が不正確になります。そのため、これに関連するアクションには依存しないようにします。
DML RETURNING文の実行で戻るResultSetオブジェクトは、ResultSetMetaData型をサポートしません。したがって、アプリケーションでは、DML RETURNING文を実行する前に、戻りパラメータの情報を把握している必要があります。
DML RETURNINGでは、ストリームはサポートされません。
DML RETURNING機能をバッチ更新と組み合せることはできません。
単一のSQL DML文の中で自動生成キー機能とDML RETURNING機能を両方とも使用することはできません。たとえば、次のような使用方法は許可されません。
...
PreparedStatement pstmt = conn.prepareStatement('insert into orders (?, ?, ?) returning order_id into ?");
pstmt.setInt(1, seq01.NEXTVAL);
pstmt.setInt(2, 100);
pstmt.setInt(3, 966431502);
pstmt.registerReturnParam(4, OracleTypes.INTEGER);
pstmt.executeUpdate;
ResultSet rset = pstmt.getGeneratedKeys;
...
Oracle JDBCドライバを使用すると、JDBCアプリケーションで、索引付き表パラメータを使用してPL/SQLをコールできます。この項の内容は次のとおりです。
|
注意: PL/SQLレコードの索引付き表はサポートされません。 |
Oracle JDBCドライバは、スカラー・データ型のPL/SQL索引付き表をサポートします。表4-2は、サポートされるスカラー型とそれに対応するJDBC型コードを示しています。
表4-2 PL/SQL型と対応するJDBC型
| PL/SQL型 | JDBC型 |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
注意: Oracle JDBCは、要素型としてRAW、DATEおよびPL/SQL RECORDをサポートしません。 |
通常のOracle JDBC入力バインド、出力登録、およびデータアクセス・メソッドは、PL/SQL索引付き表をサポートしません。この章では、これらの型をサポートするための追加のメソッドについて説明します。
OraclePreparedStatementおよびOracleCallableStatementクラスは、追加のメソッドを定義します。これらのメソッドには次のものがあります。
これらのメソッドは、PL/SQL索引付き表をIN、OUTまたはIN OUTパラメータとして、ファンクション戻り値も含めて処理します。
|
関連項目: Oracle Database PL/SQL言語リファレンス |
PL/SQL索引付き表パラメータをINパラメータ・モードでバインドするには、OraclePreparedStatementおよびOracleCallableStatementの各クラスで定義されたsetPlsqlIndexTableメソッドを使用します。
synchronized public void setPlsqlIndexTable (int paramIndex, Object arrayData, int maxLen, int curLen, int elemSqlType, int elemMaxLen) throws SQLException
表4-3では、getPlsqlIndexTableメソッドの引数について説明しています。
表4-3 setPlsqlIndexTableメソッドの引数
| 引数 | 説明 |
|---|---|
|
文内のパラメータの位置を示します。 |
|
|
PL/SQL索引付き表パラメータにバインドされる値の配列です。この値は |
|
|
一括更新で利用できる最大の |
|
|
|
|
|
|
|
|
要素型が |
次のコード例では、setPlsqlIndexTableメソッドを使用して、索引付き表をINパラメータとしてバインドします。
// Prepare the statement
OracleCallableStatement procin = (OracleCallableStatement)
conn.prepareCall ("begin procin (?); end;");
// index-by table bind value
int[] values = { 1, 2, 3 };
// maximum length of the index-by table bind value. This
// value defines the maximum possible "currentLen" for batch
// updates. For standalone binds, "maxLen" should be the
// same as "currentLen".
int maxLen = values.length;
// actual size of the index-by table bind value
int currentLen = values.length;
// index-by table element type
int elemSqlType = OracleTypes.NUMBER;
// index-by table element length in case the element type
// is CHAR, VARCHAR or RAW. This value is ignored for other
// types.
int elemMaxLen = 0;
// set the value
procin.setPlsqlIndexTable (1, values,
maxLen, currentLen,
elemSqlType, elemMaxLen);
// execute the call
procin.execute ();
この項では、PL/SQL索引付き表をOUTパラメータとして登録する方法について説明します。また、様々なマッピング・スタイルでOUTバインド値にアクセスする方法について説明します。
OUTパラメータの登録
PL/SQL索引付き表をOUTパラメータとして登録するには、OracleCallableStatementクラスで定義されたregisterIndexTableOutParameterメソッドを使用します。
synchronized public void registerIndexTableOutParameter (int paramIndex, int maxLen, int elemSqlType, int elemMaxLen) throws SQLException
表4-4では、registerIndexTableOutParameterメソッドの引数について説明しています。
表4-4 registerIndexTableOutParameterメソッドの引数
| 引数 | 説明 |
|---|---|
|
文内のパラメータの位置を示します。 |
|
|
戻される索引付き表バインド値の表の最大長を指定します。 |
|
|
|
|
|
要素型が |
次のコード例では、registerIndexTableOutParameterメソッドを使用して、索引付き表をOUTパラメータとして登録します。
// maximum length of the index-by table value. This // value defines the maximum table size to be returned. int maxLen = 10; // index-by table element type int elemSqlType = OracleTypes.NUMBER; // index-by table element length in case the element type // is CHAR, VARCHAR or FIXED_CHAR. This value is ignored for other // types int elemMaxLen = 0; // register the return value funcnone.registerIndexTableOutParameter (1, maxLen, elemSqlType, elemMaxLen);
OUTパラメータ値へのアクセス
OUTバインド値へアクセスするために、OracleCallableStatementクラスでは、様々なマッピング・スタイルの索引付き表の値を戻す複数のメソッドを定義します。JDBCドライバでは、次の3つのマッピングを選択できます。
この項の内容は次のとおりです。
JDBCデフォルト・マッピング
getPlsqlIndexTable(int)メソッドは、JDBCデフォルト・マッピングを使用して索引付き表の要素を戻します。このメソッドの構文は次のとおりです。
public Object getPlsqlIndexTable (int paramIndex) throws SQLException
表4-5では、getPlsqlIndexTableメソッドの引数について説明しています。
戻り値はJava配列です。この配列の要素は、要素のSQL型に対応するデフォルトのJava型です。たとえば、NUMERIC型コードの要素による索引付き表の場合、要素値はOracle JDBCドライバによってBigDecimalにマップされ、getPlsqlIndexTableメソッドがBigDecimal[]配列を戻します。JDBCアプリケーションの場合、戻り値をBigDecimal[]にキャストして表要素値にアクセスする必要があります。
次のコード例では、getPlsqlIndexTableメソッドを使用して、JDBCデフォルト・マッピングで索引付き表の要素を戻します。
// access the value using JDBC default mapping BigDecimal[] values = (BigDecimal[]) procout.getPlsqlIndexTable (1); // print the elements for (int i=0; i<values.length; i++) System.out.println (values[i].intValue());
Oracleマッピング
getOraclePlsqlIndexTableメソッドは、Oracleマッピングを使用して索引付き表要素を戻します。
public Datum[] getOraclePlsqlIndexTable (int paramIndex)
throws SQLException
表4-6では、getOraclePlsqlIndexTableメソッドの引数について説明しています。
戻り値はoracle.sql.Datum配列で、配列の要素は、要素のSQL型に対応するデフォルトのDatum型です。たとえば、数値要素の索引付き表の要素値は、Oracleマッピングでoracle.sql.NUMBER型にマップされ、getOraclePlsqlIndexTableメソッドはoracle.sql.NUMBER要素を含むoracle.sql.Datum配列を戻します。
次のコード例では、getOraclePlsqlIndexTableメソッドを使用して、PL/SQL索引付き表のOUTパラメータの要素に、Oracleマッピングを使用してアクセスします。
// Prepare the statement
OracleCallableStatement procout = (OracleCallableStatement)
conn.prepareCall ("begin procout (?); end;");
...
// run the call
procout.execute ();
// access the value using Oracle JDBC mapping
Datum[] outvalues = procout.getOraclePlsqlIndexTable (1);
// print the elements
for (int i=0; i<outvalues.length; i++)
System.out.println (outvalues[i].intValue());
Javaプリミティブ型マッピング
getPlsqlIndexTable(int, Class)メソッドは、Javaプリミティブ型の索引付き表の要素を戻します。戻り値はJava配列です。このメソッドの構文は次のとおりです。
synchronized public Object getPlsqlIndexTable (int paramIndex, Class primitiveType) throws SQLException
表4-7では、getPlsqlIndexTableメソッドの引数について説明しています。
表4-7 getPlsqlIndexTableメソッドの引数
| 引数 | 説明 |
|---|---|
|
文内のパラメータの位置を示します。 |
|
|
索引付き表の要素の変換先となるJavaプリミティブ型を指定します。たとえば、 このパラメータには、次の値を指定できます。
|
次のコード例では、getPlsqlIndexTableメソッドを使用して、数値のPL/SQL索引付き表の要素にアクセスします。この例では、2つ目のパラメータはjava.lang.Integer.TYPEを指定し、getPlsqlIndexTableメソッドはint配列を戻します。
OracleCallableStatement funcnone = (OracleCallableStatement)
conn.prepareCall ("begin ? := funcnone; end;");
// maximum length of the index-by table value. This
// value defines the maximum table size to be returned.
int maxLen = 10;
// index-by table element type
int elemSqlType = OracleTypes.NUMBER;
// index-by table element length in case the element type
// is CHAR, VARCHAR or RAW. This value is ignored for other
// types
int elemMaxLen = 0;
// register the return value
funcnone.registerIndexTableOutParameter (1, maxLen,
elemSqlType, elemMaxLen);
// execute the call
funcnone.execute ();
// access the value as a Java primitive array.
int[] values = (int[])
funcnone.getPlsqlIndexTable (1, java.lang.Integer.TYPE);
// print the elements
for (int i=0; i<values.length; i++)
System.out.println (values[i]);