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.3.2 パッケージoracle.sql.json
リリース20cから、Oracle Databaseでは、データベース内にネイティブのJSON SQL型が用意されています。oracle.sql.json
パッケージには、JSON型の値を使用する機能が用意されています。
特に、oracle.sql.json
パッケージを使用して次のタスクを実行できます。
- データベース内のJSON型の値の格納および取得
- JSON型の値の読取り、作成および変更
- データベースで使用されるものと同じバイナリJSON記憶域形式でのJSON型の値のエンコードまたはデコード
- JSONテキストとJSONテキスト間のJSON型の値の変換
- JSON-Pインタフェース(
javax.json.*
など)を使用したJSON型の値のバインドおよびアクセス
関連項目:
JDBC Java APIリファレンス次の例は、JSON型の値を挿入、取得および変更する方法を示しています。
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import oracle.jdbc.OracleConnection;
import oracle.jdbc.pool.OracleDataSource;
import oracle.sql.json.OracleJsonFactory;
import oracle.sql.json.OracleJsonObject;
public class JsonExample {
public static void main(String[] args) throws SQLException {
OracleDataSource ds = new OracleDataSource();
ds.setURL("jdbc:oracle:thin:@myhost:1521:orcl");
ds.setUser(<user>);
ds.setPassword(<password>);
OracleConnection con = (OracleConnection) ds.getConnection();
// create a table with a JSON column and insert one value
Statement stmt = con.createStatement();
stmt.executeUpdate("CREATE TABLE fruit (data JSON)");
stmt.executeUpdate("INSERT INTO fruit VALUES ('{"name":"pear","count":10}')");
// create another JSON object
OracleJsonFactory factory = new OracleJsonFactory();
OracleJsonObject orange = factory.createObject();
orange.put("name", "orange");
orange.put("count", 12);
// insert the orange object
PreparedStatement pstmt = con.prepareStatement("INSERT INTO fruit VALUES (:1)");
pstmt.setObject(1, orange, OracleType.JSON);
pstmt.executeUpdate();
pstmt.close();
// retrieve the pear object
ResultSet rs = stmt.executeQuery("SELECT data FROM fruit f WHERE f.data.name = 'pear'");
rs.next();
OracleJsonObject pear = rs.getObject(1, OracleJsonObject.class);
int count = pear.getInt("count");
// create a modifiable copy of the pear object
pear = factory.createObject(pear);
pear.put("count", count + 1);
pear.put("color", "green");
// update the pear object
pstmt = con.prepareStatement("UPDATE fruit f SET data = :1 WHERE f.data.name = 'pear');
pstmt.setObject(1, pear, OracleType.JSON);
pstmt.executeUpdate();
pstmt.close();
rs.close();
stmt.close();
con.close();
}
}
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
は、異なる多くの型のカーソル変数を識別するカテゴリまたはデータ型指定子と考えることができます。Oracle Databaseリリース18c以降、JDBCドライバはINバインド変数として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
は次のようにアクセスできます。
-
ストアド・プロシージャをコールするには、JDBCコール可能文またはプリペアド文を使用します。
-
ストアド・プロシージャは、
REF CURSOR
を受け入れるか、または戻します。 -
Javaアプリケーションは、コール可能文またはプリペアド文をOracleコール可能文またはOracleプリペアド文にキャストします。
-
Javaアプリケーションは、
OraclePreparedStatement
インタフェースのsetCursor
メソッドまたはOracleCallableStatement
インタフェースのgetCursor
メソッドを使用して、REF CURSOR
をJDBCResultSet
オブジェクトとしてインスタンス化します。 -
結果セットは要求どおりに処理されます。
ノート:
-
REF CURSOR
と関連付けられたカーソルは、そのREF CURSOR
を作成したStatementオブジェクトがクローズされるたびにクローズされます。 -
過去のリリースとは異なり、
REF CURSOR
のインスタンス化が行われた結果セット・オブジェクトがクローズされても、REF CURSOR
に関連付けられたカーソルはクローズされません。
-
例
この例では、REF CURSOR
データにアクセスする方法を示します。
...
// Prepare a PL/SQL call
CallableStatement cstmt =
conn.prepareCall ("DECLARE rc sys_refcursor; curid NUMBER;BEGIN open rc FOR SELECT empno FROM emp order by empno; ? := rc; END;");
cstmt.registerOutParameter (1, OracleTypes.CURSOR);
cstmt.execute ();
ResultSet rset = (ResultSet)cstmt.getObject (1);
if (rset.next ()) {
show (rset.getString ("empno"));
}
CallableStatement cstmt2 =
conn.prepareCall ("DECLARE rc sys_refcursor; v1 NUMBER; BEGIN rc := ?; fetch rc INTO v1; ? := v1; END;");
((OracleCallableStatement)call2).setCursor(1, rset);
cstmt2.registerOutParameter (2, OracleTypes.INTEGER);
cstmt2.execute();
int empno = cstmt2.getInt(2);
show("Fetch in PL/SQL empno=" + empno);
// Dump the cursor
while (rset.next ())
show (rset.getString ("empno"));
// Close all the resources
rset.close();
cstmt.close();
cstmt2.close();
...
前述の例は、次のとおりです。
-
cstmt1
とcstmt2
という2つのCallableStatement
オブジェクトがConnection
クラスのprepareCall
メソッドを使用して作成されます。 -
cstmt2
コール可能文では入力パラメータとしてREF CURSOR
を使用します。 -
コール可能文によって、
REF CURSOR
を戻すPL/SQLプロシージャが実装されます。 -
コール可能文の出力パラメータは、通常どおり登録してその型を定義する必要があります。
REF CURSOR
には、型コードOracleTypes.CURSOR
を使用します。 -
コール可能文が実行され、
REF CURSOR
を返すか、またはREF CURSOR
を入力バインドとして送信します。
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_INTEGER
または文字列の場合があります。キーは任意の値であり、稠密である必要はありません。クライアント・アプリケーションから、PLS_INTEGER
またはBINARY_INTEGER
キーのみを使用できます。
ノート:
PLS_INTEGER
とBINARY_INTEGER
は同一のデータ・タイプです。
Oracle JDBCドライバの以前のリリースでは、スカラー・データ型のPL/SQL連想配列のみがサポートされていました。また、サポートは、配列のキーと値のペアの値のみに制限されていました。Oracle Databaseリリース18cでは、連想配列のキー(索引)と値の両方へのアクセスがサポートされ、オブジェクト型の連想配列もサポートされます。新しい機能を実現するには、次のメソッドを使用します。
Array createOracleArray(String arrayTypeName, Object elements) throws SQLException
ARRAY createARRAY(String typeName, Object elements) throws SQLException
前述のメソッドの両方で、2番目のパラメータは、連想配列のキーと値のペアを保持する
java.util.Map<Integer, ?>
にすることも、または値の配列だけにすることもできます。これが値の配列である場合、JDBCドライバによって索引が0,1,2などにデフォルト設定されます。java.util.Map<Integer, ?>
である場合、JDBCドライバによってキーはデフォルト設定されません。マップで指定されたままになり、疎と負の場合があります。Map<?,?> oracle.jdbc.OracleArray.getJavaMap();
このメソッドは、連想配列のデータ型に
Map<?,?>
を戻し、ネストした表およびVARRAYにnull
を戻します。
ノート:
-
連想配列は、以前は索引付き表と呼ばれていました。
-
文字列のデータ型を使用する場合、サイズはPL/SQLのサイズ(32767文字)に制限されます。サーバー側内部ドライバの場合、制限は小さくなります。
関連項目:
-
Oracle Database JDBC Java APIリファレンス
- 連想配列の詳細は、これらを参照してください