Oracleには、Java Database Connectivity(JDBC)標準の実装を拡張するJavaクラスとインタフェースが用意されており、開発者は、Oracleデータ型にアクセスして操作し、Oracleパフォーマンス拡張要素を使用できます。標準JDBCに比べて、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
は常により速く、サポートされていない2〜3のキャラクタ・セットを除き、同じキャラクタ・セットを表現するため、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 release 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リターニングは、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準拠のデータ型に対応したクラスもあります。これらのクラスは、表4-1に示すようにoracle.sql.Datum
クラスを拡張すると同時に、java.sql
パッケージの標準JDBC 2.0インタフェースを実装します。
注意: 可能な場合はJDBC標準型またはJava型の使用をお薦めします。パッケージoracle.sql.* の方は主に下位互換性、またはOracleの少数の特定機能(OPAQUE 、OraData 、TIMESTAMPTZ など)のサポートのために用意されています。 |
oracle.sqlパッケージのクラス
表4-1に、oracle.sql
データ型クラスとそれに対応するOracle SQL型のリストを示します。
表4-1 Oracleデータ型クラス
Javaクラス | 実装されるOracle SQL型とインタフェース |
---|---|
|
|
|
|
|
|
|
|
|
SQL |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
注意: LONG およびLONG RAW のSQL型と、REF CURSOR 型カテゴリには、oracle.sql.* クラスは含まれません。これらの型では、標準JDBC機能を使用してください。たとえば、LONG またはLONG RAW データを、標準JDBC結果セットおよびコール可能文メソッドgetBinaryStream およびgetCharacterStream を使用して入力ストリームとして取り出します。REF CURSOR 型にはgetCursor メソッドを使用します。 |
データ型クラスに加え、oracle.sql
パッケージには、主にオブジェクトとコレクションで使用するための次のサポート・クラスとインタフェースが含まれます。
oracle.sql.ArrayDescriptor
このクラスは、oracle.sql.ARRAY
オブジェクトの作成に使用します。配列のSQL型を記述します。
oracle.sql.StructDescriptor
このクラスは、oracle.sql.STRUCT
オブジェクトの作成に使用します。このオブジェクトは、データベース内のOracleオブジェクトへのデフォルト・マッピングとして使用できます。
oracle.sql.ORAData
およびoracle.sql.ORADataFactory
これらのインタフェースは、Oracleオブジェクト・サポートのOracle ORAData
シナリオを実装するJavaクラスで使用します。
oracle.sql.OpaqueDescriptor
このクラスは、oracle.sql.OPAQUE
クラスのインスタンスにメタデータを取得する際に使用します。
oracle.sql.TypeDescriptor
このクラスは、一時SQL型および永続SQL型をJavaで表すのに使用します。
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の概要
特定のOracleオブジェクト型では、一般にSQLとJava間でカスタム・マッピングを定義することをお薦めします。たとえば、SQLData
カスタムJavaクラスを使用する場合、このマッピングは型マップで定義する必要があります。
ただし、マッピングを定義しない場合は、オブジェクト型からのデータはoracle.sql.STRUCT
クラスのインスタンス内でJavaによってインスタンス化されます。
STRUCT
クラスは、標準JDBC 2.0 java.sql.Struct
インタフェースを実装し、oracle.sql.Datum
クラスを拡張します。
STRUCT
オブジェクトは、OracleオブジェクトのRAWバイトのJava表現です。これにはOracleオブジェクトのSQL型名とSQL形式で属性値を保持するoracle.sql.Datum
オブジェクトの配列が含まれます。
STRUCT
オブジェクトを作成する場合、oracle.jdbc.OracleConnection
インタフェースのcreateStruct
メソッドを使用します。STRUCT
を作成するためのこのファクトリ・メソッドのシグネチャは、次のとおりです。
Struct createStruct (String typeName, Object[] attributes) throws SQLException
このシグネチャのパラメータは次のとおりです。
typeName
パラメータは、STRUCTオブジェクト名がマップされるSQL構造型のSQL型名です。typeName
は、このデータベース用に定義されたユーザー定義の型の名前です。これはStruct.getSQLTypeName
メソッドが戻す値です。
attributes
パラメータは、戻されたオブジェクトに移入される属性を指定します。
STRUCT
オブジェクトの属性は、getOracleAttributes
メソッドを使用する場合はoracle.sql.Datum[]
オブジェクトとして、getAttributes
メソッドを使用する場合はjava.lang.Object[]
オブジェクトとしてインスタンス化できます。属性をoracle.sql.*
オブジェクトとしてインスタンス化すると、oracle.sql.*
形式の次の利点を利用できます。
oracle.sql.*
形式でoracle.sql.STRUCT
データをインスタンス化すると、SQL形式でデータが完全に保持されます。変換は実行されません。これは、データにアクセスしても表示する必要がない場合に便利です。
Javaアプリケーションでは自由度の高い方法でデータをリストアできます。
クラスoracle.sql.REFの概要
oracle.sql.REF
クラスは、Oracleオブジェクト参照をサポートする一般クラスです。このクラスは、すべてのoracle.sql.*
データ型のクラスと同様に、oracle.sql.Datum
クラスのサブクラスです。このクラスは、標準JDBC 2.0 java.sql.Ref
インタフェースを実装します。
REF
クラスには、オブジェクト参照を取り出して渡すためのメソッドがあります。ただし、オブジェクト参照の選択によって取り出されるのは、オブジェクトへのポインタのみです。これによってオブジェクト自体がインスタンス化されることはありません。ただし、REF
クラスにはオブジェクト・データを取り出して渡すためのメソッドも含まれています。
JDBCアプリケーションではREF
オブジェクトを作成できません。データベースから取り出すことができるのは、既存のREF
オブジェクトのみです。
クラス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
インタフェースを実装します。
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
これらのクラスは、標準JDBCの一部であるプリミティブSQLデータ型にマップされ、対応するJDBC Java型間での変換を提供します。
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.Calendar
クラスを使用して指定します。
注意: タイムゾーン・オブジェクトの作成にはTimeZone.getTimeZone を使用しないでください。これは、Oracleのタイムゾーン・データ型では、JDKよりも多くのタイムゾーン名をサポートしているためです。 |
次のコードは、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
データを調整することができます。
クラス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
クラスにも、対応する別の定数は定義されていません。
次のコードは、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.jdbc.driver.ROWID のかわりに、oracle.sql.ROWID クラスを使用します。このクラスは、以前のリリースのOracle JDBCで使用されていました。ただし、J2SE 1.5を使用する場合のみ以前のクラスを使用します。JSE 6の場合は、かわりにjava.sql.RowId インタフェースを使用します。 |
例
次の例では、ROWIDデータに対するアクセスおよび操作の方法を示します。
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); oracle.sql.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リリース1(11.1)では、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-2に、oracle.jdbc
パッケージに含まれる接続に使用する主なインタフェースとクラス、文および結果セットのリストを示します。
表4-2 oracle.jdbcパッケージの主なインタフェースおよびクラス
名前 | インタフェースまたはクラス | 主要機能 |
---|---|---|
|
クラス |
|
|
インタフェース |
Oracle Databaseインスタンスを起動または停止するためのメソッド、Oracle Statementオブジェクトを戻すメソッド、およびカレント接続で実行される任意の文に対応したOracleパフォーマンス拡張要素を設定するメソッドを提供します。
|
|
インタフェース |
文ごとにOracleパフォーマンス拡張要素を設定するメソッドを提供します。
|
|
インタフェース |
|
|
インタフェース |
データを
|
|
インタフェース |
|
|
インタフェース |
列名やデータ型などの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アドバンスト・アプリケーション開発者ガイド』 |
次のoracle.jdbc.OracleConnection
メソッドは、Oracle定義の拡張機能です。
このインタフェースは、標準JDBC文の機能を拡張するインタフェースで、OraclePreparedStatement
およびOracleCallableStatement
クラスのスーパーインタフェースです。拡張機能には、文単位でOracleパフォーマンス拡張要素用のフラグおよびオプションの設定のサポートが含まれます。この機能は、接続単位でこれらの設定を行うOracleConnection
インタフェースと対照的な役割を果します。
次のoracle.jdbc.OracleStatement
メソッドは、Oracle定義の拡張機能です。
このインタフェースは、OracleStatement
インタフェースを拡張し、標準JDBCのプリコンパイルされたSQL文の機能を拡張します。また、oracle.jdbc.OraclePreparedStatement
インタフェースはOracleCallableStatement
インタフェースによって拡張されます。拡張機能には、プリコンパイルされたSQL文にoracle.sql.*
型とオブジェクトをバインドするset
XXX
メソッド、および文単位で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
型の場合)
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 ();
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リターニング機能は、自動生成キーの取出しに比べて、より豊富な機能を提供します。この機能は、自動生成キーの取出しに使用できますが、アプリケーションで使用する可能性がある他の列や値の取出しにも使用できます。
注意:
|
次の各項では、DMLリターニング機能のサポートについて説明します。
OraclePreparedStatement
インタフェースは、DMLリターニングをサポートするOracle固有のApplication Program Interface(API)に伴って機能拡張されました。DMLリターニングによって戻されるパラメータおよび取り出されるデータを登録するために、registerReturnParameter
メソッドおよびgetReturnResultSet
メソッドがoracle.jdbc.OraclePreparedStatement
インタフェースに追加されています。
DMLリターニング機能の戻りパラメータは、registerReturnParameter
メソッドを使用して登録します。エラーが発生した場合、メソッドはSQLException
インスタンスをスローします。戻りパラメータの索引を指定する正の整数を渡す必要があります。また、戻りパラメータの型も指定する必要があります。戻りパラメータの最大バイト数または最大文字数も指定できます。このメソッドは、char
またはRAW
型でのみ使用できます。SQL構造型の完全修飾名も指定できます。
注意: 戻りパラメータの最大サイズが不明な場合は、デフォルトの最大サイズを選択するregisterReturnParameter(int paramIndex, int externalType) を使用してください。戻りパラメータの最大サイズが判明している場合は、registerReturnParameter(int paramIndex, int externalType, int maxSize) を使用することでメモリー消費を抑制できます。 |
getReturnResultSet
メソッドは、DMLリターニング機能で戻されたデータをフェッチし、ResultSet
オブジェクトとして戻します。エラーが検出された場合は、SQLException
例外が発生します。
注意: DMLリターニング機能のためのOracle固有のAPIは、Java Development Kit(JDK)1.5の場合はojdbc5.jar 、JDK 1.6の場合はojdbc6.jar に含まれています。 |
DMLリターニング文を実行する前に、JDBCアプリケーションが、registerReturnParameter
メソッドを1つ以上コールする必要があります。これらのメソッドは、戻りパラメータに関する型やサイズなどの情報をJDBCドライバに提供します。DMLリターニング文は、executeUpdate
またはexecute
のいずれかの標準JDBC APIを使用して処理されます。戻されたパラメータは、oracle.jdbc.OraclePreparedStatement
インタフェースのgetReturnResultSet
メソッドを使用して、ResultSet
オブジェクトとしてフェッチできます。
ResultSet
オブジェクトの値を読み取るには、基礎となるStatement
オブジェクトをオープンする必要があります。基礎となるStatement
オブジェクトがクローズされている場合は、戻されたResultSet
オブジェクトもクローズ状態となります。この状態は、SQL問合せ文を処理することで取り出されたResultSet
オブジェクトの状態と一致します。
DMLリターニング文を実行する場合、getReturnResultSet
メソッドで戻されるResultSet
オブジェクトの同時実行性はCONCUR_READ_ONLY
であり、そのResultSet
オブジェクト型はTYPE_FORWARD_ONLY
またはTYPE_SCROLL_INSENSITIVE
である必要があります。
ここでは、DMLリターニング機能に関する2つのコード例を示します。
次のコードは、DMLリターニング機能の使用例です。この例では、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リターニング機能の使用例です。ただし、この例では、戻りパラメータの最大サイズが不明です。したがって、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リターニング機能を使用する場合は、次の点に注意してください。
getReturnResultSet
メソッドを複数回起動した場合は、その戻り値が不正確になります。そのため、これに関連するアクションには依存しないようにします。
DMLリターニング文の実行で戻るResultSet
オブジェクトは、ResultSetMetaData
型をサポートしません。したがって、アプリケーションでは、DMLリターニング文を実行する前に、戻りパラメータの情報を把握している必要があります。
DMLリターニングでは、ストリームはサポートされません。
DMLリターニング機能をバッチ更新と組み合せることはできません。
単一のSQL DML文の中で自動生成キー機能とDMLリターニング機能を両方とも使用することはできません。たとえば、次のような使用方法は許可されません。
... 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-3に、サポートされるスカラー型とそれに対応するJDBC型コードを示します。
表4-3 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-4に、getPlsqlIndexTable
メソッドの引数を示します。
表4-4 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-5に、registerIndexTableOutParameter
メソッドの引数を示します。
表4-5 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-6に、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-7に、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-8に、getPlsqlIndexTable
メソッドの引数を示します。
表4-8 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]);