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クラスのget
XXX
メソッドを自動的に定義します。このメソッドはデータを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型に変換するのに適切なxxx
Value
メソッド。たとえば、stringValue
、intValue
、booleanValue
、dateValue
およびbigDecimalValue
があげられます。
補足的な変換メソッド。データをストリームとして取り出すラージ・オブジェクト(LOB)クラスのメソッド、およびオブジェクト参照を使用してオブジェクト・データの取出しや設定を行うREF
クラスのメソッドなど、データ型の機能に適したget
XXX
およびset
XXX
。
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標準ファクトリ・メソッドを使用する必要があります。たとえば、CLOB
BLOB
NCLOB
などです。
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文にバインドするためのset
XXX
メソッド
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結果セットの機能を拡張し、get
XXX
メソッドを実装してデータを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]);