4 Oracle拡張機能
Oracleには、Java Database Connectivity(JDBC)標準の実装を拡張するJavaクラスとインタフェースが用意されており、開発者は、Oracleデータ型にアクセスして操作し、Oracleパフォーマンス拡張機能を使用できます。この章では、JDBC標準実装を拡張するためにOracleで提供されるクラスとインタフェースの概要を示します。また、この拡張機能がサポートする主な機能についても説明します。
この章の構成は、次のとおりです。
関連トピック
4.1 Oracle拡張機能の概要
標準機能に加えて、Oracle JDBCドライバにはOracle固有型拡張機能およびパフォーマンス拡張機能があります。これらの拡張機能は、次のJavaパッケージに用意されています。
-
oracle.sql
Oracle形式でSQLデータを示すクラスを提供します。
-
oracle.jdbc
Oracle型形式でのデータベース・アクセスおよび更新をサポートするためのインタフェースを提供します。
関連トピック
4.2 Oracle拡張機能
JDBCへのOracle拡張機能には、Oracle Databaseを操作する能力を高めるいくつかの機能があります。次のようなものがあります:
4.2.1 JDBCを使用したデータベース管理
Oracle Database 11gリリース1以降、2つのJDBCメソッド、startup
およびshutdown
がoracle.jdbc.OracleConnection
インタフェースに追加されており、これによりOracle Databaseインスタンスの起動と停止を実行できます。
ノート:
My Oracle Supportノート335754.1に、Oracle Database 11g JDBCドライバでoracle.jdbc.driver.*
パッケージがサポート対象外であることが記載されています。つまり、Oracle Database 10gリリース2がこのパッケージをサポートする最後のデータベースであり、現在のリリースのデータベースでは、oracle.jdbc.driver.*
パッケージに依存するすべてのAPIはコンパイルできなくなります。このようなAPIを削除して、標準のAPIに移行する必要があります。たとえば、コードでoracle.jdbc.CustomDatum
およびoracle.jdbc.CustomDatumFactory
インタフェースを使用する場合、これらをjava.sql.Struct
またはjava.sql.SQLData
インタフェースで置き換える必要があります。
関連トピック
4.2.2 Oracleデータ型のサポート
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
型は、下位互換性のためにのみサポートされており、使用は推奨されません。
4.2.3 Oracleオブジェクトのサポート
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.jdbc.OracleData
インタフェースのいずれかを実装している必要があります。各インタフェースは、SQLとJavaとの間でデータ変換を行うメソッドを指定します。
ノート:
Oracle Database 12cリリース1 (12.1)以降、OracleData
インタフェースはORAData
インタフェースに置き換わりました。
Oracleオブジェクトに対応するカスタムJavaクラスを作成する場合は、Oracle JVM Webサービス・コールアウト・ユーティリティを使用することをお薦めします。
4.2.4 スキーマの命名サポート
Oracleオブジェクト・データ型クラスには、完全修飾スキーマ名の受入れおよび復帰を行う機能があります。完全修飾スキーマ名は、次の構文になります。
{[schema_name].}[sql_type_name]
ここで、schema_name
はスキーマの名前、sql_type_name
はオブジェクトのSQL型名で、schema_name
とsql_type_name
はピリオド(.
)で区切られています。
JDBCでオブジェクト型を指定するには、その完全修飾名を使用します。型名が現行ネームスペース内、つまり現行スキーマ内にある場合は、スキーマ名を入力する必要はありません。スキーマは、次の規則に従って命名されます。
-
スキーマ名と型名は、どちらも引用符で囲んでも囲まなくてもかまいません。ただし、
CORPORATE.EMPLOYEE
のように、SQL型名にピリオドが含まれている場合は、型名を引用符で囲む必要があります。 -
JDBCドライバは、オブジェクト名内の引用符で囲まれていない最初のピリオドを検索して、ピリオドの前の文字列をスキーマ名として使用し、ピリオドの後の文字列を型名として使用します。ピリオドが見つからない場合、JDBCドライバは現行スキーマをデフォルトとします。つまり、オブジェクト型名が現行スキーマに属している場合は、完全修飾名を指定するかわりに、スキーマを指定せずに型名のみを指定できます。これが、型名にピリオドが含まれない場合に型名を引用符で囲む理由です。
たとえば、ユーザー
HR
がperson.address
という型を作成し、自分のセッション内でそれを使用するとします。HR
は、スキーマ名を省略して、person.address
で型をJDBCドライバに渡します。この場合、person.address
を引用符で囲まないとピリオドが検出され、JDBCドライバはperson
をスキーマ名、address
を型名として誤って解釈してしまいます。 -
JDBCは、オブジェクト型名の文字列をデータベースにそのまま渡します。つまり、JDBCドライバは、オブジェクト型名が引用符で囲まれていてもその大/小文字を変更しません。
たとえば、
HR.PersonType
がJDBCドライバにオブジェクト型名として渡されると、JDBCドライバはその文字列をそのままデータベースに渡します。別の例として、型名の文字列内に空白文字が含まれている場合、JDBCドライバは空白文字を削除しません。
4.2.5 DML RETURNING
Oracle Databaseでは、データ操作言語(DML)文にRETURNING
句を使用できます。これによって、2つのSQL文を1文に結合できます。DML RETURNINGは、Oracle JDBC Oracle Call Interface(OCI)ドライバとOracle JDBC Thinドライバの両方でサポートされます。
関連項目:
4.3 Oracle JDBCパッケージ
この項では、Oracle JDBC拡張機能をサポートする、次のJavaパッケージについて説明します。
4.3.1 パッケージoracle.sql
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
メソッドを使用します。
ノート:
可能な場合はJDBC標準型またはJava型の使用をお薦めします。パッケージoracle.sql.*
の方は主に下位互換性、またはOracleの少数の特定機能(OPAQUE
、OracleData
、TIMESTAMPTZ
など)のサポートのために用意されています。
oracle.sql.*データ型の一般的なサポート
各Oracleデータ型クラスは、特に次の機能をサポートします。
-
SQLデータ用のJavaバイト配列であるデータ記憶域。
-
SQLデータをバイト配列で戻す
getBytes()
メソッド。 -
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.STRUCT
クラスは、java.sql.Struct
インタフェースのOracle実装です。このクラスは値クラスです。構成後にクラスの内容を変更しないでください。このクラスは、すべてのoracle.sql.*
データ型のクラスと同様に、oracle.sql.Datum
クラスのサブクラスです。
ノート:
Oracle Database 12cリリース1 (12.1)以降、oracle.sql.STRUCT
クラスは非推奨となり、oracle.jdbc.OracleStruct
インタフェースに置き換えられています。このインタフェースはoracle.jdbc
パッケージに属します。標準互換性には(可能であれば)java.sql
パッケージの使用可能なメソッドを使用し、Oracle固有の拡張機能にはoracle.jdbc
パッケージの使用可能なメソッドを使用することを強くお薦めします。oracle.jdbc.OracleStruct
インタフェースの詳細は、MoSノート1364193.1を参照してください。
クラスoracle.sql.REFの概要
oracle.sql.REF
クラスは、Oracleオブジェクト参照をサポートする一般クラスです。このクラスは、すべてのoracle.sql.*
データ型のクラスと同様に、oracle.sql.Datum
クラスのサブクラスです。
ノート:
Oracle Database 12cリリース1 (12.1)以降、oracle.sql.REF
クラスは非推奨となり、oracle.jdbc.OracleRef
インタフェースに置き換えられています。このインタフェースはoracle.jdbc
パッケージに属します。標準互換性には(可能であれば)java.sql
パッケージの使用可能なメソッドを使用し、Oracle固有の拡張機能にはoracle.jdbc
パッケージの使用可能なメソッドを使用することを強くお薦めします。oracle.jdbc.OracleRef
インタフェースの詳細は、MoSノート1364193.1を参照してください。
REF
クラスには、オブジェクト参照を取り出して渡すためのメソッドがあります。ただし、オブジェクト参照の選択によって取り出されるのは、オブジェクトへのポインタのみです。これによってオブジェクト自体がインスタンス化されることはありません。ただし、REF
クラスにはオブジェクト・データを取り出して渡すためのメソッドも含まれています。JDBCアプリケーションではREF
オブジェクトを作成できません。データベースから取り出すことができるのは、既存のREF
オブジェクトのみです。
oracle.sql.REF
を使用するのではなく、JDBC標準型、java.sql.Ref
およびJDBC標準メソッドを使用する必要があります。コードを移植可能にする場合、Oracle JDBCドライバのみがoracle.sql.REF
型のインスタンスを使用するので、標準型を使用する必要があります。
クラスoracle.sql.BLOB、oracle.sql.CLOB、oracle.sql.BFILEの概要
バイナリ・ラージ・オブジェクト(BLOB)、キャラクタ・ラージ・オブジェクト(CLOB)およびバイナリ・ファイル(BFILE)は、大きすぎてデータベース表に直接格納できないデータ項目に使用します。一方、データベース表はデータの実際の場所を指すロケータを格納します。
ノート:
-
Oracle Database 12cリリース1 (12.1)以降、
oracle.sql.BLOB
クラスおよびOracle.sql.CLOB
クラスは非推奨となり、それぞれoracle.jdbc.OracleBlob
インタフェースおよびoracle.jdbc.OracleClob
インタフェースに置き換えられています。これらのインタフェースはoracle.jdbc
パッケージに属します。標準互換性には(可能であれば)java.sql
パッケージの使用可能なメソッドを使用し、Oracle固有の拡張機能にはoracle.jdbc
パッケージの使用可能なメソッドを使用することを強くお薦めします。oracle.jdbc.OracleBlob
インタフェースおよびoracle.jdbc.OracleClob
インタフェースの詳細は、MoSノート1364193.1を参照してください。 -
oracle.sql.BFILE
はOracle独自の拡張機能であり、これに相当するJDBC標準機能はありません。
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
表現がありません。たとえば、OracleのBINARY_FLOAT
データ型およびBINARY_DOUBLE
データ型の場合、負のゼロは正のゼロに強制変換され、NaNはすべて正規のものに強制変換されます。そのため、oracle.sql.NUMBER
クラスを使用して、Double.NaN
値またはFloat.NaN
値が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
クラスを使用して指定します。
ノート:
-
タイムゾーン・オブジェクトの作成には
TimeZone.getTimeZone
を使用しないでください。これは、Oracleのタイムゾーン・データ型では、JDKよりも多くのタイムゾーン名をサポートしているためです。 -
結果セットの
TIMESTAMPLTZ
列の後にLONG
列が続く場合、LONG
列を読み取ろうとするとエラーになります。
次のコードは、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.TIMESTAMPTZ
-
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
型では、インスタンスの連続バイトにのみアクセスできます。
ノート:
Oracle Database 12cリリース1 (12.1)以降、oracle.sql.OPAQUE
クラスは非推奨となり、oracle.jdbc.OracleOpaque
インタフェースに置き換えられています。このインタフェースはoracle.jdbc
パッケージに属します。標準互換性には(可能であれば)java.sql
パッケージの使用可能なメソッドを使用し、Oracle固有の拡張機能にはoracle.jdbc
パッケージの使用可能なメソッドを使用することをお薦めします。oracle.jdbc.OracleOpaque
インタフェースの詳細は、MoSノート1364193.1を参照してください。
4.4 Oracle文字データ型のサポート
Oracle文字データ型には、SQL CHARおよびNCHARデータ型が含まれます。次の各項では、oracle.sql.*
クラスを使用してこれらのデータ型にアクセスする方法について説明します。
4.4.1 SQL CHARデータ型
SQL CHARデータ型には、CHAR
、VARCHAR2
およびCLOB
データ型が含まれます。これらのデータ型を使用すると、文字データをデータベース文字セットのコード体系で格納できます。データベースの文字セットは、データベースの作成時に決まります。
4.4.2 SQL NCHARデータ型
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
クラスにも、対応する別の定数は定義されていません。
ノート:
setFormOfUse
メソッドは、registerOutParameter
メソッドをコールする前にコールして、予測できない結果を回避する必要があります。
次のコードは、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();
4.4.3 クラスoracle.sql.CHAR
oracle.sql.CHAR
クラスは、文字データを処理および変換するためにOracle JDBCによって使用されます。このクラスは、文字データを変換するためのグローバリゼーション・サポート機能を提供します。このクラスには、グローバリゼーション・サポート文字セットおよび文字データという2つの主要な属性があります。グローバリゼーション・サポート文字セットは、文字データのエンコーディングを定義します。これは、CHAR
オブジェクトの作成時に必ず渡されるパラメータです。グローバリゼーション・サポート文字セット情報がない状態では、CHAR
オブジェクト内のデータ・バイトは無意味です。oracle.sql.CHAR
クラスは、SQL CHAR
およびSQL NCHAR
の両方のデータ型に使用されます。
ノート:
10g リリース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
オブジェクトに格納されます。ノート:
-
CharacterSet
オブジェクトをNULL値にすることはできません。 -
CharacterSet
クラスは抽象クラスであるため、コンストラクタを持ちません。インスタンスを作成するには、make
メソッドを使用するのが唯一の方法です。 -
サーバーは、特別な値である
CharacterSet.DEFAULT_CHARSET
をデータベース文字セットとして認識します。クライアントの場合、この値は無意味です。 -
ユーザーが
CharacterSet
クラスを拡張することを、オラクル社は意図しておらず、お薦めもしません。
-
oracle.sql.CHAR変換メソッド
CHAR
クラスは、文字データを文字列に変換するための次のようなメソッドを提供します。
-
getString
このメソッドは、
CHAR
オブジェクトによって表された文字のシーケンスを文字列に変換し、JavaString
オブジェクトを戻します。無効なOracleID
を入力した場合、文字セットは認識されず、getString
メソッドはSQLException
例外をスローします。 -
toString
このメソッドは
getString
メソッドと同じです。ただし、無効なOracleID
を入力すると、文字セットが認識されず、toString
メソッドによりCHAR
データの16進表現が戻されます。SQLException
例外はスローされません。 -
getStringWithReplacement
このメソッドは
getString
メソッドと同一ですが、CHAR
オブジェクトの文字セットにUnicode表現のない文字が、デフォルトの置換文字で置き換えられる点が異なります。デフォルトの置換文字は文字セットによって異なりますが、多くの場合は疑問符(?
)です。
データベース・サーバーとクライアント、またはクライアント上で動作するアプリケーションでは、異なる文字セットを使用できます。CHAR
クラスのメソッドを使用してデータをサーバーとクライアント間で転送する場合、JDBCドライバはデータをサーバーの文字セットからクライアントの文字セットに(またはその逆に)変換する必要があります。データを変換する際、ドライバはグローバリゼーション・サポートを使用します。
関連項目:
4.5 その他のOracle型拡張機能
Oracle JDBCドライバは、Oracle固有のBFILE
データ型、ROWID
データ型およびREF
CURSOR
型をサポートしますが、これらは標準JDBC仕様に含まれていません。このセクションでは、ROWID
およびREF CURSOR
型の拡張について説明します。ROWID
はJava文字列としてサポートされ、REF
CURSOR
型はJDBC結果セットとしてサポートされます。
この項の内容は次のとおりです。
4.5.1 Oracle ROWID型
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 5.0を使用する場合のみとしてください。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 first_name, rowid FROM employees FOR UPDATE"); // Prepare a statement to update the first_name column at a given ROWID PreparedStatement pstmt = conn.prepareStatement ("UPDATE employees SET first_name = ? 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 }
4.5.2 OracleのREF CURSOR型のカテゴリ
カーソル変数は、問合せ作業領域の(内容でなく)メモリーの場所を保持します。カーソル変数を宣言すると、ポインタが作成されます。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コール可能文を使用します。出力パラメータがあるため、プリペアド文ではなく、コール可能文を使用する必要があります。
-
ストアド・プロシージャによって
REF CURSOR
が戻されます。 -
Javaアプリケーションによってコール可能文がOracleコール可能文にキャストされ、
OracleCallableStatement
クラスのgetCursor
メソッドを使用してREF CURSOR
がJDBCResultSet
オブジェクトとしてインスタンス化されます。 -
結果セットは要求どおりに処理されます。
ノート:
REF CURSOR
と関連付けられたカーソルは、そのREF CURSOR
を作成したStatementオブジェクトがクローズされるたびにクローズされます。過去のリリースとは異なり、
REF CURSOR
のインスタンス化が行われた結果セット・オブジェクトがクローズされても、REF CURSOR
に関連付けられたカーソルはクローズされません。
例
この例では、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 first_name from employees; 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
オブジェクトに戻されます。
4.5.3 Oracle BINARY_FLOAT型およびBINARY_DOUBLE型
Oracle BINARY_FLOAT
型およびBINARY_DOUBLE
型は、IEEE 574のfloat型とdouble型のデータを格納するために使用します。これらの型は、負とゼロおよびNaN
を除いて、Javaのfloat
スカラー型とdouble
スカラー型に相当します。
BINARY_DOUBLE
列を問合せに含めると、データはデータベースからバイナリ形式で取り出されます。getDouble
メソッドも、データをバイナリ形式で戻します。一方、NUMBER
データ型の列の場合は、数値ビットが戻り、Javaのdouble
データ型に変換されます。
ノート:
SQL FLOAT
型、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
についても同じ内容が適用されます。
4.5.4 Oracle SYS.ANYTYPE型およびSYS.ANYDATA型
Oracle Database 12cリリース1 (12.1)では、SYS.ANYTYPE
およびSYS.ANYDATA
というOracle型にアクセスするためのJavaインタフェースが提供されています。
関連項目:
これらのOracle型の詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください
SYS.ANYTYPE
型のインスタンスには、オブジェクト型およびコレクション型も含め、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 ( employee_id NUMBER, first_name VARCHAR2(10) )
次の方法で、SQLオブジェクト型EMPLOYEE
のインスタンスを作成し、anydata_table
に挿入することができます。
... PreparedStatement pstmt = conn.prepareStatement("insert into anydata_table values (?,?)"); Struct myEmployeeStr = conn.createStruct("EMPLOYEE", new Object[]{1120, "Papageno"}); ANYDATA anyda = ANYDATA.convertDatum(myEmployeeStr); pstmt.setInt(1,123); pstmt.setObject(2,anyda); pstmt.executeUpdate(); ...
例4-6 データベース表からのANYDATA列の選択
... Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("select data from anydata_table"); while(rs.next()) { ANYDATA obj = (ANYDATA)rs.getObject(1); TypeDescriptor td = obj.getTypeDescriptor(); } rs.close(); stmt.close(); ...
4.5.5 oracle.jdbcパッケージ
oracle.jdbc
パッケージのインタフェースは、java.sql
のインタフェースに対するOracle拡張機能を定義します。これらの拡張機能によって、この章に記載されているSQL形式のデータへのアクセスが可能になります。また、Oracleパフォーマンス拡張要素など、Oracle固有の他の機能へのアクセスも可能になります。
表4-1に、oracle.jdbc
パッケージに含まれる接続に使用する主なインタフェースとクラス、文および結果セットのリストを示します。
表4-1 oracle.jdbcパッケージの主なインタフェースおよびクラス
名前 | インタフェースまたはクラス | 主要機能 |
---|---|---|
|
クラス |
|
|
インタフェース |
Oracle Databaseインスタンスを起動または停止するためのメソッド、Oracle Statementオブジェクトを戻すメソッド、および現行接続で実行される任意の文に対応したOracleパフォーマンス拡張機能を設定するメソッドを提供します。
|
|
インタフェース |
文ごとにOracleパフォーマンス拡張機能を設定するメソッドを提供します。
|
|
インタフェース |
SELECT文を実行しないでプリペアド文からメタデータを取得する
|
|
インタフェース |
データを
|
|
インタフェース |
|
|
インタフェース |
列名やデータ型などのOracle結果セットのメタデータ情報を取得するメソッドを提供します。
|
|
クラス |
データベース製品名/バージョン、表情報、デフォルト・トランザクション分離レベルなどのデータベースに関するメタデータ情報を取得するメソッドを提供します。
|
|
クラス |
SQL型を識別する整数定数を定義します。 標準型の場合、同じ値を標準 |
|
インタフェース |
配列全体を取り出し、配列要素のサブセットを取り出し、配列要素のSQLベース型名を取り出すための機能があります。 |
|
インタフェース |
|
|
インタフェース |
|
|
インタフェース |
|
|
インタフェース |
|
|
インタフェース |
4.5.5.1 インタフェースoracle.jdbc.OracleConnection
このインタフェースは、標準JDBC接続機能を拡張して、Oracle Statementオブジェクトの作成と取得、Oracleパフォーマンス拡張機能用のフラグやオプションの設定、Oracleオブジェクト用型マップのサポート、およびクライアント識別子のサポートを実施します。
Oracle Database 11gリリース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より前では、引数として
ARRAY
およびSTRUCT
クラス・コンストラクタに渡すために、ArrayDescriptors
およびStructDescriptors
を作成する必要がありました。新しいARRAY
およびStruct
ファクトリ・メソッドは記述子の引数がありません。ドライバはまだ内部で記述子を使用していますが、作成する必要はありません。
クライアント識別子
クライアント識別子を接続プーリング環境で使用すると、データベース・セッションを現在使用している軽量ユーザーを識別できます。クライアント識別子を使用すると、異なるデータベース・セッション間でグローバル・アクセス・アプリケーション・コンテキストを共有することもできます。データベース・セッションで設定されたクライアント識別子は、データベース監査がオンにされたときに監査されます。
関連項目:
詳細は、Oracle Database JDBC Java APIリファレンスを参照してください
4.5.5.3 インタフェースoracle.jdbc.OraclePreparedStatement
このインタフェースは、OracleStatement
インタフェースを拡張し、標準JDBCのプリペアド文の機能を拡張します。また、oracle.jdbc.OraclePreparedStatement
インタフェースはOracleCallableStatement
インタフェースによって拡張されます。拡張機能は次の機能から構成されます。
-
oracle.sql.*
型とオブジェクトをプリペアド文にバインドするためのset
XXX
メソッド -
SELECT文を実行しないで、プリペアド文からメタデータを取得するための
getMetaData
メソッド -
文単位でOracleパフォーマンス拡張機能をサポートするためのメソッド
ノート:
:NEW
または:OLD
列を参照するトリガーの作成にPreparedStatement
インタフェースを使用しないでください。かわりに、Statement
を使用してください。PreparedStatement
を使用すると、実行が失敗し、メッセージ「java.sql.SQLException: INまたはOUTパラメータがありません - 索引:: 1
」が発行されます。
4.5.5.4 インタフェースoracle.jdbc.OracleCallableStatement
このインタフェースは、OracleStatement
インタフェースを拡張するOraclePreparedStatement
インタフェースを機能拡張し、標準JDBCのコール可能文機能を組み込みます。
ノート:
:NEW
または:OLD
列を参照するトリガーの作成にCallableStatement
インタフェースを使用しないでください。かわりにStatement
を使用してください。CallableStatement
を使用すると、実行が失敗し、メッセージ「java.sql.SQLException: INまたはOUTパラメータがありません - 索引:: 1
」が発行されます。
ノート:
-
set
XXX
(String,...)
とregisterOutParameter(String,...)
メソッドは、すべてのバインドがプロシージャまたは関数パラメータのみの場合にかぎり使用できます。文はそれ以外のバインドを含むことができません。パラメータ・バインドは疑問符で示す必要があります(:
XX
ではなく、?)
。 -
set
XXX
(int,...)
またはset
XXX
AtName(String,...)
メソッドを使用している場合、出力パラメータは、名前付きパラメータを指定するためのregisterOutParameter(String,...)
ではなく、registerOutParameter(int,...)
を使用してバインドされます。
4.5.5.6 インタフェースoracle.jdbc.OracleResultSetMetaData
4.5.5.7 クラスoracle.jdbc.OracleTypes
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
例外がスローされます。
次の例では、プリペアド文を使用してNULL値をデータベースに挿入します。NULL
に設定する数値オブジェクトの識別にはOracleTypes.NUMERIC
を使用することに注意してください。ただし、Types.NUMERIC
も使用されることがあります。
PreparedStatement pstmt = conn.prepareStatement ("INSERT INTO num_table VALUES (?)"); pstmt.setNull (1, OracleTypes.NUMERIC); pstmt.execute ();
この例では、プリペアド文を使用して、EMPLOYEE
型のNULL
STRUCT
オブジェクトをデータベースに挿入します。
PreparedStatement pstmt = conn.prepareStatement ("INSERT INTO employees 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);
4.6 DML RETURNING
DML RETURNING機能は、自動生成キーの取出しに比べて、より豊富な機能を提供します。この機能は、自動生成キーの取出しに使用できますが、アプリケーションで使用する可能性がある他の列や値の取出しにも使用できます。
ノート:
-
サーバー側内部ドライバは、DML RETURNINGおよび自動生成キーの取出しをサポートしていません。
-
同一文中でDML RETURNINGと自動生成キーの取得の両方を使用することはできません。
次の各項では、DML RETURNING機能のサポートについて説明します。
関連項目:
4.6.1 Oracle固有のAPI
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) 6.0の場合はojdbc6.jar
、JDK 7の場合はojdbc7.jar
に含まれています。
4.6.2 DML RETURNING文の実行について
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
である必要があります。
4.6.3 DML RETURNINGの例
ここでは、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); ... } ...
4.6.4 DML RETURNINGの制限事項
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; ...
4.7 PL/SQL連想配列へのアクセス
Oracle JDBCドライバを使用すると、JDBCアプリケーションで、連想配列パラメータを使用してPL/SQLをコールできます。PL/SQLでは、連想配列はキー値ペアのセットです。キーはPLS_INTEGERs
または文字列の場合があります。キーは任意の値であり、稠密である必要はありません。クライアント・アプリケーションから、PLS_INTEGER
キーのみを使用できます。このキーは正の数で稠密である必要があります。
ノート:
連想配列は、以前は索引付き表と呼ばれていました。
この項の内容は次のとおりです。
4.7.1 PL/SQL連想配列の概要
Oracle JDBCドライバは、VARCHAR
型およびNUMBER
型のPL/SQL連想配列をサポートします。通常のOracle JDBC入力バインド、出力登録、およびデータ・アクセス・メソッドは、PL/SQL連想配列をサポートしません。この項では、これらの型をサポートする追加メソッドを説明します。
OraclePreparedStatement
およびOracleCallableStatement
クラスは、追加のメソッドを定義します。このようなメソッドには、次のようなものがあります。
-
setPlsqlIndexTable
-
registerIndexTableOutParameter
-
getOraclePlsqlIndexTable
-
getPlsqlIndexTable
これらのメソッドは、PL/SQL連想配列をIN
、OUT
またはIN OUT
パラメータとして、ファンクション戻り値も含めて処理します。
ノート:
文字列のデータ型を使用する場合、サイズはPL/SQLのサイズ(32767文字)に制限されます。サーバー側内部ドライバの場合、制限は小さくなります。これらのメソッドの詳細は、Javadocを参照してください。
関連項目:
-
Oracle Database JDBC Java APIリファレンス
- 連想配列の詳細は、これらを参照してください
4.7.2 PL/SQL連想配列でのINパラメータのバインド
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-2では、getPlsqlIndexTable
メソッドの引数について説明しています。
表4-2 setPlsqlIndexTableメソッドの引数
引数 | 説明 |
---|---|
|
文内のパラメータの位置を示します。 |
|
PL/SQL連想配列パラメータにバインドされる値の配列です。この値は |
|
一括更新で利用できる最大の |
|
|
|
|
|
要素型が |
次のコード例では、連想配列をIN
としてバインドするsetPlsqlIndexTable
メソッドを使用します。
// Prepare the statement OracleCallableStatement procin = (OracleCallableStatement) conn.prepareCall ("begin procin (?); end;"); // Associative Array bind value int[] values = { 1, 2, 3 }; // maximum length of the Associative Array 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 Associative Array bind value int currentLen = values.length; // Associative Array element type int elemSqlType = OracleTypes.NUMBER; // Associative Array 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 ();
4.7.3 PL/SQL連想配列でのOUTパラメータの受取り
この項では、PL/SQL連想配列をOUT
パラメータとして登録する方法について説明します。また、様々なマッピング・スタイルでOUT
バインド値にアクセスする方法について説明します。
ノート:
この項で説明するメソッドは、ファンクション戻り値およびIN OUT
パラメータ・モードに適用されます。
OUTパラメータの登録
PL/SQL連想配列をOUT
パラメータとして登録するには、OracleCallableStatement
クラスで定義されたregisterIndexTableOutParameter
メソッドを使用します。
synchronized public void registerIndexTableOutParameter (int paramIndex, int maxLen, int elemSqlType, int elemMaxLen) throws SQLException
表4-3では、registerIndexTableOutParameter
メソッドの引数について説明しています。
表4-3 registerIndexTableOutParameterメソッドの引数
引数 | 説明 |
---|---|
文内のパラメータの位置を示します。 |
|
|
戻される連想配列バインド値の表の最大長を指定します。 |
|
|
|
要素型が |
次のコード例では、registerIndexTableOutParameter
メソッドを使用して、連想配列をOUT
パラメータとして登録します。
// maximum length of the Associative Array value. This // value defines the maximum table size to be returned. int maxLen = 10; // Associative Array element type int elemSqlType = OracleTypes.NUMBER; // Associative Array 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デフォルト・マッピング |
|
Oracleマッピング |
|
Javaプリミティブ型マッピング |
|
4.7.4 PL/SQL連想配列の型マッピング
この項の内容は次のとおりです。
JDBCデフォルト・マッピング
getPlsqlIndexTable(int)
メソッドは、JDBCデフォルト・マッピングを使用して連想配列の要素を戻します。このメソッドの構文は次のとおりです。
public Object getPlsqlIndexTable (int paramIndex) throws SQLException
表4-4では、getPlsqlIndexTable
メソッドの引数について説明しています。
表4-4 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-5では、getOraclePlsqlIndexTable
メソッドの引数について説明しています。
表4-5 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-6では、getPlsqlIndexTable
メソッドの引数について説明しています。
表4-6 getPlsqlIndexTableメソッドの引数
引数 | 説明 |
---|---|
|
文内のパラメータの位置を示します。 |
|
連想配列の要素の変換先となるJavaプリミティブ型を指定します。たとえば、 このパラメータには、次の値を指定できます。
|
次のコード例では、getPlsqlIndexTable
メソッドを使用して、数値のPL/SQL連想配列の要素にアクセスします。この例では、2つ目のパラメータはjava.lang.Integer.TYPE
を指定し、getPlsqlIndexTable
メソッドはint
配列を戻します。
OracleCallableStatement funcnone = (OracleCallableStatement) conn.prepareCall ("begin ? := funcnone; end;"); // maximum length of the Associative Array value. This // value defines the maximum table size to be returned. int maxLen = 10; // Associative Array element type int elemSqlType = OracleTypes.NUMBER; // Associative Array 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]);