16 Oracleコレクションの操作
この章では、Java配列とそのデータにマップされるOracleコレクションにアクセスして操作するための、標準Java Database Connectivity(JDBC)に対するOracleの拡張機能について説明します。次の内容について説明します。
ノート:
Oracle Database 12cリリース1 (12.1)以降、oracle.sql.ARRAY
クラスは非推奨となり、oracle.jdbc.OracleArray
インタフェースに置き換えられています。このインタフェースはoracle.jdbc
パッケージに属します。標準互換性には(可能であれば)java.sql
パッケージの使用可能なメソッドを使用し、Oracle固有の拡張機能にはoracle.jdbc
パッケージの使用可能なメソッドを使用することをお薦めします。oracle.jdbc.OracleArray
インタフェースの詳細は、MoSノート1364193.1を参照してください。
16.1 コレクションのためのOracle拡張機能
この項の内容は次のとおりです。
16.1.1 Oracleコレクションの概要
データベース内の変数配列(VARRAY)またはNESTED TABLEのいずれかであるOracleコレクションは、Javaでは配列にマップされます。JDBC 2.0配列は、JavaでOracleコレクションをインスタンス化するために使用されます。コレクションおよび配列という用語は、どちらも同じ意味で使用されることがあります。ただし、データベース側ではコレクション、JDBCアプリケーション側では配列のほうが適切です。
サポートされるのは、SQL型名を指定することでコレクションの型を記述できる、名前付きコレクションのみです。JDBCを使用すると、次のものに配列を使用できます。
-
SELECT
句の列 -
IN
またはOUT
バインド変数 -
Oracleオブジェクトの属性
-
他の配列の要素
16.1.2 コレクションのインスタンス化に関する選択
アプリケーションでは、弱い型指定のoracle.sql.ARRAY
クラスのインスタンスとして、または事前に作成した強い型指定のカスタムJavaクラスのインスタンスとしてコレクションをインスタンス化するオプションがあります。コレクションのために使用するカスタムJavaクラスは、カスタム・コレクション・クラスと呼びます。カスタム・コレクション・クラスは、Oracleのoracle.jdbc.OracleData
インタフェースを実装する必要があります。さらに、カスタム・クラスまたはコンパニオン・クラスは、oracle.jdbc.OracleDataFactory
を実装する必要があります。標準java.sql.SQLData
インタフェースは、SQLオブジェクト型のマッピング専用です。
oracle.sql.ARRAY
クラスは、標準のjava.sql.Array
インタフェースを実装します。
ARRAY
クラスには、配列全体を取り出し、配列要素のサブセットを取り出し、配列要素のSQLベース型名を取り出すための機能があります。ただし、setterメソッドがないため、配列に書き込むことはできません。
カスタム・コレクション・クラスを使用すると、ARRAY
クラスと同様に、配列のすべてまたは一部を取得して、SQLベース型名を取得できます。強い型指定により、実行時まで検出できない可能性のあるコーディング・エラーを、コンパイル時に発見できる利点もあります。
ノート:
VARRAYへのアクセスとNESTED TABLEへのアクセス間で、コード上の違いはありません。ARRAY
クラス・メソッドは、VARRAYまたはNESTED TABLEに適用されているかどうかを判断し、適切なアクションを決定して応答します。
16.1.3 コレクションの作成
Oracleは名前付きコレクションのみをサポートしているため、特定のVARRAY
型名またはNESTED TABLE型名を制限する必要があります。VARRAYとNESTED TABLEは、型自体ではなく型のカテゴリです。
次のSQL CREATE TYPE
文を使用してコレクションを作成すると、コレクションにSQL型名が割り当てられます。
CREATE TYPE <sql_type_name> AS <datatype>;
VARRAYは、サイズ可変の配列です。順序付けられたデータ要素のセットを保持し、要素はすべて同じデータ型です。各要素は、索引を持ちますが、これはVARRAY.における要素の位置に対応する番号です。VARRAY内の要素数は、そのVARRAYのサイズを表します。VARRAY
型を宣言する場合は、最大サイズを指定する必要があります。次に例を示します。
CREATE TYPE myNumType AS VARRAY(10) OF NUMBER;
この文では、10要素以下のNUMBER
値を持つVARRAYが記述されたSQL型名として、myNumType
が定義されています。
ネストした表は順序を設定していないデータ要素のセットで、すべて同じデータ型です。ネストした表はデータベースの別の表に格納されます。この表は単一の列を持ち、この列の型は組込み型またはオブジェクト型です。表がオブジェクト・タイプの場合、オブジェクト・タイプの各属性の列を持つ複数列の表として表示されることがあります。ネストした表は、次のようにして作成することができます。
CREATE TYPE myNumList AS TABLE OF integer;
この文は、INTEGER
型のNESTED TABLEに使用される表タイプが定義されたSQL型名として、myNumList
を指定しています。
16.1.4 マルチ・レベルのコレクション型の作成
JDBCにおいてマルチ・レベルのコレクション型を作成する最も一般的な方法は、java.sql.Statement
クラスのexecute
メソッドにSQLのCREATE TYPE
文を渡すことです。次のコードは、first_level
という1レベルのNESTED TABLEと、second_level
という2レベルのNESTED TABLEを作成します。
Connection conn = .... // make a database // connection Statement stmt = conn.createStatement(); // open a database // cursor stmt.execute("CREATE TYPE first_level AS TABLE OF NUMBER"); // create a nested // table of number stmt.execute("CREATE TYPE second_level AS TABLE OF first_level"); // create a // two-levels nested table ... // other operations here stmt.close(); // release the // resource conn.close(); // close the // database connection
マルチ・レベルのコレクション型を作成すると、実表の列またはオブジェクト型の属性として使用できます。
ノート:
マルチ・レベルのコレクション型は、Oracle9i以降でのみ使用可能です。
16.2 コレクション機能の概要
結果セットまたはコール可能文によって配列インスタンス内のコレクション・データを取得し、プリペアド文またはコール可能文内のバインド変数として戻すことができます。
標準java.sql.Array
インタフェースを実装するoracle.sql.ARRAY
クラスは、Oracleコレクションのデータにアクセスし、更新するために必要な機能を提供します。
この項では、配列のgetterメソッドとsetterメソッドについて説明します。Java配列としてコレクションを取り出し、渡すには、次の結果セット、コール可能文およびプリペアド文メソッドを使用します。
ノート:
Oracle Database 12cリリース1 (12.1)以降、oracle.sql.ARRAY
クラスは非推奨となり、oracle.jdbc.OracleArray
インタフェースに置き換えられています。このインタフェースはoracle.jdbc
パッケージに属します。標準互換性には(可能であれば)java.sql
パッケージの使用可能なメソッドを使用し、Oracle固有の拡張機能にはoracle.jdbc
パッケージの使用可能なメソッドを使用することをお薦めします。oracle.jdbc.OracleArray
インタフェースの詳細は、MoSノート1364193.1を参照してください。
結果セットおよびコール可能文のgetterメソッド
OracleResultSet
インタフェースとOracleCallableStatement
インタフェースは、出力パラメータとして、つまりoracle.sql.ARRAY
インスタンスまたはjava.sql.Array
インスタンスとしてARRAY
オブジェクトを取り出すために、getARRAY()
メソッドとgetArray()
メソッドをサポートします。getObject
メソッドも使用できます。これらのメソッドは、入力としてString
列名またはint
列索引を取ります。
ノート:
Oracle JDBCドライバは、配列および構造の記述子をキャッシュします。これには多数のパフォーマンス上の利点がありますが、データベース内で配列型の基礎となる型定義を変更すると、その配列型のキャッシュされた記述子は古くなり、アプリケーションでSQLException
が通知されます。
プリペアド文およびコール可能文のsetterメソッド
OraclePreparedStatement
クラスとOracleCallableStatement
クラスは、更新されたARRAY
オブジェクトをバインド変数として取ってデータベースに渡すsetARRAY
メソッドとsetArray
メソッドをサポートします。setObject
メソッドも使用できます。これらのメソッドは、oracle.sql.ARRAY
インスタンスまたはjava.sql.Array
インスタンスに加えて、String
パラメータ名またはint
パラメータ索引を入力として取ります。
16.3 ARRAYパフォーマンス拡張要素メソッド
この項では、次の項目について説明します。
16.3.1 Javaプリミティブ型の配列としてのoracle.sql.ARRAY要素へのアクセスについて
oracle.sql.ARRAY
クラスには、配列要素をJavaプリミティブ型として戻すメソッドが含まれています。これらのメソッドを使用すると、Datum
インスタンスとしてコレクション要素にアクセスしてからDatum
インスタンスをJavaプリミティブ型に変換する方法に比べ、より容易にコレクション要素にアクセスできます。
ノート:
oracle.sql.ARRAY
クラスのこれらの特殊なメソッドは、数値コレクションに制限されます。
最初のシグネチャを使用している各メソッドは、コレクション要素をXXX
[]
の形式で戻します。ここで、XXX
はJavaプリミティブ型です。第2のシグネチャを使用している各メソッドは、count
によって指定される数の要素を含んでいて、index
の場所で開始されるコレクションのスライスを戻します。
16.3.2 ARRAY自動要素バッファリング
Oracle JDBCドライバには、ARRAY
の内容のバッファリングを有効または無効にするためのパブリック・メソッドが用意されています。
oracle.sql.ARRAY
クラスには、次のメソッドがあります。
-
setAutoBuffering
-
getAutoBuffering
ARRAY
要素にgetAttributes
およびgetArray
の各メソッドで複数回アクセスし、ARRAY
データがオーバーフローせずにJava仮想マシン(JVM)のメモリーに格納されると想定する場合は、JDBCアプリケーションで自動バッファリングを有効にすることをお薦めします。
ノート:
変換した要素をバッファリングすると、JDBCアプリケーションでは、大量のメモリーが消費されます。
自動バッファリングを有効にすると、oracle.sql.ARRAY
オブジェクトでは、変換したすべての要素のローカルのコピーが保持されます。このデータが保持されるため、この情報に2回目にアクセスするときにはデータ・フォーマット変換処理を実行しなくて済みます。
16.3.3 ARRAY自動索引作成
配列を自動索引作成モードにすると、配列オブジェクトは配列要素へのアクセスを迅速に行うために索引表をメンテナンスします。
oracle.sql.ARRAY
クラスには、自動配列索引作成をサポートする次のメソッドが含まれています。
-
setAutoIndexing(boolean)
-
setAutoIndexing(boolean, int)
デフォルトでは、自動索引作成は有効にされていません。JDBCアプリケーションで、getArray
およびgetResultSet
の各メソッドを使用して配列要素のランダム・アクセスを実行する場合は、ARRAY
オブジェクトの自動索引作成を有効にします。
16.4 配列の作成と使用方法
この項では、配列オブジェクトを作成する方法と、配列オブジェクトとしてコレクションを取り出し、渡す方法について説明します。内容は次のとおりです。
16.4.1 ARRAYオブジェクトの作成
ノート:
Oracle JDBCでは、java.sql.Connection
インタフェースのJDBC 4.0のcreateArrayOf
メソッドはサポートされていません。Oracleの配列型はすべて名前付きですが、このメソッドでは匿名の配列型のみが許容されています。かわりにOracle固有のメソッド、oracle.jdbc.OracleConnection.createARRAY
を使用してください。
この項では、ARRAY
オブジェクトを作成する方法について説明します。この項の内容は次のとおりです。
ARRAYオブジェクトの作成に関するステップ
Oracle Database 11gリリース1以降、oracle.jdbc.OracleConnection
インタフェースのcreateARRAY
ファクトリ・メソッドを使用して配列オブジェクトを作成することができます。配列を作成するファクトリ・メソッドは次のように定義されています。
public ARRAY createARRAY(java.lang.String typeName,java.lang.Object elements)throws SQLException
ここで、typeName
は、作成されたオブジェクトのSQL型の名前で、elements
は作成されたオブジェクトの要素です。
ノート:
コレクション型の名前は、要素の型名と同じではありません。次に例を示します。
CREATE TYPE person AS object
(c1 NUMBER(5), c2 VARCHAR2(30));
CREATE TYPE array_of_persons AS varray(10)
OF person;
前述の文では、コレクション型の名前は、ARRAY_OF_PERSON
です。コレクション要素のSQL型名は、PERSON
です。
例16-1 マルチ・レベル・コレクションの作成
JDBCアプリケーションは、シングル・レベル・コレクションと同様、oracle.sql.ARRAY
インスタンスを作成してマルチ・レベル・コレクションを表し、インスタンスをデータベースに送信することができます。シングル・レベル・コレクションを作成するために使用するのと同じcreateARRAY
ファクトリ・メソッドを使用することによってマルチ・レベル・コレクションを作成することもできます。シングル・レベル・コレクションを作成する場合、要素は一次元のJava配列ですが、マルチ・レベル・コレクションを作成する場合、要素はoracle.sql.ARRAY[]
要素の配列、ネストJava配列、またはその組合せです。
次のコードは、ネストしたJava配列を使用してコレクション型を作成する方法を示します。
// prepare the multilevel collection elements as a nested Java array int[][][] elements = { {{1}, {1, 2}}, {{2}, {2, 3}}, {{3}, {3, 4}} }; // create the ARRAY using the factory method ARRAY array = oracle.jdbc.OracleConnection.createARRAY(sql_type_name, elements);
16.4.2 配列とその要素の取出し
この項では、結果セットからARRAY
インスタンス全体を取り出す方法を最初に説明し、次にARRAY
インスタンスから要素を取り出す方法について説明します。この項の内容は次のとおりです。
16.4.2.1 配列の取出しについて
oracle.sql.ARRAY
オブジェクトを戻すgetARRAY
メソッドを使用して、結果セットをOracleResultSet
オブジェクトにキャストすることで、SQL配列を結果セットから取り出すことができます。結果セットをキャストするのを避けるには、java.sql.ResultSet
インタフェースによって指定された標準のgetObject
メソッドを使用してデータを取得し、その出力をoracle.sql.ARRAY
にキャストします。
16.4.2.2 データ取出しメソッド
ARRAY
オブジェクトを作成した後は、次に示すoracle.sql.ARRAY
クラスの3つのオーバーロード・メソッドのいずれかを使用して、データを取り出すことができます。
-
getArray
-
getOracleArray
-
getResultSet
Oracleは配列のすべての要素、またはサブセットを取り出すことができるメソッドも提供しています。
ノート:
構造化オブジェクトの配列を操作している場合は、Oracleは、オブジェクトをJavaにマップする方法を選択できるように、型マップを指定できる次の3つのメソッドのバージョンを提供します。
getOracleArray
getOracleArray()
メソッドは、標準Array
インタフェースでは指定されていないOracle固有の拡張機能です。getOracleArray
メソッドでは、配列の要素値を取り出してDatum[]
配列に格納します。この要素は、元の配列のSQL型データに対応するoracle.sql.*
データ型です。
構造化オブジェクトの配列では、このメソッドは要素のためにoracle.jdbc.OracleStruct
インスタンスを使用します。
また、getOracleArray(
index
,
count
)
メソッド
を使用すると、配列要素のサブセットを取得できます。
getResultSet
getResultSet
メソッドは、ARRAY
オブジェクトによって示される配列の要素が含まれる結果セットを戻します。結果セットは配列要素ごとに1行を含み、各行には2つの列があります。最初の列には、配列内でその要素を参照する索引が格納され、2つめの列には要素値が格納されます。VARRAYの場合、索引は配列内での要素の位置を表します。定義上、順序付けられていないネスト表の場合、索引は特定の問合せにおける要素の戻り順のみを反映します。
NESTED TABLEからデータを取り出すときは、getResultSet
を使用することをお薦めします。NESTED TABLEの要素数には、制限はありません。メソッドから戻されたResultSet
オブジェクトのポインタの初期値は、データの第1行です。next
メソッドおよび適切なget
XXX
メソッドを使用すると、NESTED TABLEの内容を取得できます。また、getArray
を使用すると、NESTED TABLEのすべての内容が一度に戻されます。
getResultSet
メソッドでは、接続のデフォルト型マップを使用して、OracleオブジェクトのSQL型とその対応するJavaデータ型間のマッピングを決定します。接続のデフォルト型マップを使用しない場合は、getResultSet(
map
)
を使用して別の型マップを指定できます。
また、getResultSet(
index
,
count
)
およびgetResultSet(
index
,
count
,
map
)
メソッドを使用すると、配列のサブセットを取り出すことができます。
getArray
getArray
メソッドは、必要に応じてキャストできるjava.lang.Object
として配列要素を戻す標準JDBCメソッドです。要素は、元の配列のSQL型データに対応するJava型データに変換されます。
また、getArray(
index
,
count
)
メソッドを使用すると、配列要素のサブセットを取り出すことができます。
16.4.2.3 データ取出しメソッドの比較
配列要素を戻すためにgetOracleArray
を使用する場合は、そのメソッドがoracle.sql.Datum
インスタンスを使用するため、SQLからJavaへのデータ変換を行う必要がなくなります。Datum
クラスまたはそのサブクラスのインスタンス内にある文字以外のデータは、RAW SQL形式で保持されます。
getResultSet
を使用してプリミティブ・データ型の配列を戻す場合、JDBCドライバはResultSet
オブジェクトを戻します。このオブジェクトには、各要素ごとに、その要素を配列内で参照する索引と要素値が含まれます。次に例を示します。
ResultSet rset = intArray.getResultSet();
この場合、結果セットには、1つの配列要素ごとに1つの行があり、各行には2つの列があります。最初の列には、配列内でその要素を参照する索引が格納され、2つめの列には要素値が格納されます。
配列の要素が、Java型にマップするSQL型の場合、getArray
はこのJava型の要素の配列を戻します。getArray
メソッドの戻り型はjava.lang.Object
です。したがって、結果は使用する前にキャストする必要があります。
BigDecimal[] values = (BigDecimal[]) intArray.getArray();
ここで、intArray
はoracle.sql.ARRAY
で、NUMBER
型のVARRAYに対応しています。values
配列にはjava.math.BigDecimal
型の要素の配列が含まれます。これはSQL NUMBER
データ型が、デフォルトで、Oracle JDBCドライバによって、Java BigDecimal
にマップされるためです。
ノート:
BigDecimal
の使用は、リソースを大量に消費するJavaの操作です。Oracle JDBCは数値SQLデータをデフォルトでBigDecimal
にマップするため、getArray
を使用するとパフォーマンスに影響を与える可能性があり、数値のコレクションの場合は推奨されません。
16.4.2.4 型マップに従った構造化オブジェクト配列の要素の取出し
デフォルトでは、構造化オブジェクトの要素を持つ配列を操作しているときに、getArray
またはgetResultSet
を使用すると、デフォルト・マッピングに従って配列のOracleオブジェクトが、対応するJavaデータ型にマップされます。これは、これらのメソッドでは、接続のデフォルト型マップを使用してマッピングが決定されるためです。
ただし、デフォルトの処理を変更する場合は、getArray(
map
)
またはgetResultSet(
map
)
メソッドを使用して、別のマッピングを含む型マップを指定できます。配列のOracleオブジェクトに対応するエントリが型マップに存在する場合は、配列の各オブジェクトは、その型マップで指定されている、対応するJava型にマップされます。次に例を示します。
Object[] object = (Object[])objArray.getArray(map);
この例のobjArray
はoracle.sql.ARRAY
オブジェクトを表し、map
はjava.util.Map
オブジェクトを表します。
型マップに特定のOracleオブジェクトに対応するエントリが含まれない場合、要素はoracle.jdbc.OracleStruct
オブジェクトとして戻されます。
getResultSet(
map
)
メソッドは、getArray(
map
)
メソッドと同じように動作します。
関連トピック
16.4.2.5 配列要素のサブセットの取出し
配列の内容全体を取り出さない場合は、サブセットを取り出すことができるgetArray
、getResultSet
およびgetOracleArray
のシグネチャを使用できます。配列のサブセットを取り出すには、索引と件数を渡して、取出しを開始する配列の位置および取り出す要素数を指定します。前の例と同様に、接続に対して型マップを指定するか、またはデフォルトの型マップを使用して、Java型に変換します。次に例を示します。
Object object = arr.getArray(index, count, map); Object object = arr.getArray(index, count);
getResultSet
を使用した例です。
ResultSet rset = arr.getResultSet(index, count, map); ResultSet rset = arr.getResultSet(index, count);
getOracleArray
を使用した例です。
Datum[] arr = arr.getOracleArray(index, count);
arr
はoracle.sql.ARRAY
オブジェクト、index
はlong
型、count
はint
型、map
はjava.util.Map
オブジェクトを表します。
ノート:
配列全体ではなく、配列のサブセットを取り出すことにパフォーマンス上の利点はありません。
16.4.2.6 oracle.sql.Datum配列への配列要素の取出し
oracle.sql.Datum[]
配列を戻すには、getOracleArray
を使用します。戻される配列の要素は、元の配列要素のSQLデータ型に対応するoracle.sql.*
型です。次に例を示します。
Datum arraydata[] = arr.getOracleArray();
arr
はoracle.sql.ARRAY
オブジェクトを表します。
次の例は、接続オブジェクトconn
および文オブジェクトstmt
がすでに作成済であることを前提としています。この例では、SQL型名NUM_ARRAY
の配列がNUMBER
データのVARRAYを格納するために作成されます。NUM_ARRAY
は、表VARRAY_TABLE
に格納されます。
問合せは、VARRAY_TABLE
の内容を選択します。結果セットはOracleResultSet
にキャストされます。それに対してgetARRAY
メソッドが適用され、配列データがmy_array
に取得されます。これはoracle.sql.ARRAY
オブジェクトです。
my_array
はoracle.sql.ARRAY
型の配列であるため、getSQLTypeName
メソッドおよびgetBaseType
メソッドをこの配列に適用すれば、その配列の要素ごとに、その整数コードでSQL型名を戻すことができます。
次に、プログラムにより配列の内容が出力されます。NUM_ARRAY
の内容はSQLデータ型NUMBER
であるため、my_array
の要素はBigDecimal
型です。要素を使用するには、最初に、その要素をBigDecimal
にキャストする必要があります。for
ループでは、配列の各値はBigDecimal
にキャストされ、標準出力に出力されます。
stmt.execute ("CREATE TYPE num_varray AS VARRAY(10) OF NUMBER(12, 2)"); stmt.execute ("CREATE TABLE varray_table (col1 num_varray)"); stmt.execute ("INSERT INTO varray_table VALUES (num_varray(100, 200))"); ResultSet rs = stmt.executeQuery("SELECT * FROM varray_table"); ARRAY my_array = ((OracleResultSet)rs).getARRAY(1); // return the SQL type names, integer codes, // and lengths of the columns System.out.println ("Array is of type " + array.getSQLTypeName()); System.out.println ("Array element is of type code " + array.getBaseType()); System.out.println ("Array is of length " + array.length()); // get Array elements BigDecimal[] values = (BigDecimal[]) my_array.getArray(); for (int i=0; i<values.length; i++) { BigDecimal out_value = (BigDecimal) values[i]; System.out.println(">> index " + i + " = " + out_value.intValue()); }
getResultSet
を使用して配列を取得する場合は、最初に結果セット・オブジェクトを取得し、次にnext
メソッドを使用して操作を反復する必要があるので、注意が必要です。getInt
メソッドでは、パラメータの索引を使用して、要素の索引および要素値を取り出します。
ResultSet rset = my_array.getResultSet(); while (rset.next()) { // The first column contains the element index and the // second column contains the element value System.out.println(">> index " + rset.getInt(1)+" = " + rset.getInt(2)); }
16.4.2.7 マルチ・レベル・コレクション要素へのアクセスについて
oracle.sql.ARRAY
クラスは、コレクション要素にアクセスするために、オーバーロードされた3つのメソッドを提供します。JDBCドライバは、これらのメソッドをマルチ・レベル・コレクションをサポートするように拡張します。これらのメソッドを次に示します。
-
getArray
メソッド -
getOracleArray
メソッド -
getResultSet
メソッド
getArray
メソッドは、コレクション要素を保持するJava配列を戻します。配列要素の型は、コレクション要素の型とJDBCのデフォルトの変換マトリックスによって決まります。
たとえば、getArray
メソッドは、SQL NUMBER
型のコレクションのjava.math.BigDecimal
配列を戻します。getOracleArray
メソッドは、Datum
形式でコレクション要素を保持するDatum
配列を戻します。マルチ・レベル・コレクションの場合、getArray
メソッドおよびgetOracleArray
メソッドはいずれも、oracle.sql.ARRAY
要素のJava配列を戻します。
getResultSet
メソッドは、マルチ・レベル・コレクション要素をラップするResultSet
オブジェクトを戻します。マルチ・レベル・コレクションの場合、JDBCアプリケーションはResultSet
クラスのgetObject
、getARRAY
またはgetArray
メソッドを使用して、oracle.sql.ARRAY
のインスタンスとしてコレクション要素にアクセスします。
次のコードは、getOracleArray
、getArray
およびgetResultSet
メソッドの使用方法を示します。
Connection conn = ...; // make a JDBC connection Statement stmt = conn.createStatement (); ResultSet rset = stmt.executeQuery ("select col2 from tab2 where idx=1"); while (rset.next()) { ARRAY varray3 = (ARRAY) rset.getObject (1); Object varrayElems = varray3.getArray (1); // access array elements of "varray3" Datum[] varray3Elems = (Datum[]) varrayElems; for (int i=0; i<varray3Elems.length; i++) { ARRAY varray2 = (ARRAY) varray3Elems[i]; Datum[] varray2Elems = varray2.getOracleArray(); // access array elements of "varray2" for (int j=0; j<varray2Elems.length; j++) { ARRAY varray1 = (ARRAY) varray2Elems[j]; ResultSet varray1Elems = varray1.getResultSet(); // access array elements of "varray1" while (varray1Elems.next()) System.out.println ("idx="+varray1Elems.getInt(1)+" value="+varray1Elems.getInt(2)); } } } rset.close (); stmt.close (); conn.close ();
16.4.3 配列の文オブジェクトへの引渡し
この項では、プリペアド文オブジェクトまたはコール可能文オブジェクトに配列を渡す方法について説明します。
配列のプリペアド文への引渡し
次の手順に従って、配列をプリペアド文に渡します。
ノート:
配列は、IN
またはOUT
バインド変数として使用できます。
-
プリペアド文に
oracle.sql.ARRAY
オブジェクトとして渡す配列を定義します。ARRAY array = oracle.jdbc.OracleConnection.createARRAY(sql_type_name, elements);
sql_type_name
は配列のユーザー定義SQL型名を指定するJava文字列を表し、elements
は要素のJava配列を含むjava.lang.Object
を表します。 -
実行するSQL文を含む
java.sql.PreparedStatement
オブジェクトを作成します。 -
プリペアド文を
OraclePreparedStatement
にキャストし、setARRAY()
を使用して、プリペアド文に配列を渡します。(OraclePreparedStatement)stmt.setARRAY(parameterIndex, array);
parameterIndex
はパラメータ索引を表し、array
は手順2で作成したoracle.sql.ARRAY
オブジェクトを表します。 -
プリペアド文を実行します。
配列のコール可能文への引渡し
16.5 型マップを使用した配列要素のマップ
配列にOracleオブジェクトが含まれる場合は、型マップを使用して、配列のオブジェクトを、対応するJavaクラスに関連付けることができます。型マップを指定しない場合または型マップに特定のOracleオブジェクトのエントリが含まれない場合、各要素はoracle.jdbc.OracleStruct
オブジェクトとして戻されます。
型マップを使用して、配列のOracleオブジェクトと対応するJavaクラスとのマッピングを決定するときは、マップに適切なエントリを追加する必要があります。
次の例では、型マップを使用して配列要素をカスタムJavaオブジェクト・クラスにマップする方法を説明します。この例の配列は、NESTED TABLEです。この例では、まず、名前属性と従業員番号属性が設定されているEMPLOYEE
オブジェクトを定義します。EMPLOYEE_LIST
はEMPLOYEE
オブジェクトのNESTED TABLE型です。次に、会社内の部署名および各部署の従業員名を格納するEMPLOYEE_TABLE
を作成します。EMPLOYEE_TABLE
の中では、従業員はEMPLOYEE_LIST
表の形式で格納されます。
stmt.execute("CREATE TYPE EMPLOYEE AS OBJECT (EmpName VARCHAR2(50),EmpNo INTEGER))"); stmt.execute("CREATE TYPE EMPLOYEE_LIST AS TABLE OF EMPLOYEE"); stmt.execute("CREATE TABLE EMPLOYEE_TABLE (DeptName VARCHAR2(20), Employees EMPLOYEE_LIST) NESTED TABLE Employees STORE AS ntable1"); stmt.execute("INSERT INTO EMPLOYEE_TABLE VALUES ("SALES", EMPLOYEE_LIST (EMPLOYEE('Susan Smith', 123), EMPLOYEE('Lee Brown', 124)))");
SALES
部門に属するすべての従業員をカスタム・オブジェクト・クラスEmployeeObj
のインスタンスの配列に取り込む場合は、EMPLOYEE
SQL型とEmployeeObj
カスタム・オブジェクト・クラス間のマッピングを指定するために、型マップにエントリを追加する必要があります。
これを実行するには、まず文と結果セット・オブジェクトを作成し、次に、SALES
部門に関連付けられているEMPLOYEE_LIST
を結果セットに選択します。getARRAY
メソッドを使用してEMPLOYEE_LIST
をARRAY
オブジェクト(次の例ではemployeeArray
)に取得できるように、結果セットをOracleResultSet
にキャストします。
この例のEmployeeObj
カスタム・オブジェクト・クラスは、SQLData
インタフェースを実装しています。
Statement s = conn.createStatement(); OracleResultSet rs = (OracleResultSet)s.executeQuery ("SELECT Employees FROM employee_table WHERE DeptName = 'SALES'"); // get the array object ARRAY employeeArray = ((OracleResultSet)rs).getARRAY(1);
EMPLOYEE_LIST
オブジェクトを取り出したので、既存の型マップを取得し、SQL型EMPLOYEE
をJava型EmployeeObj
にマップするエントリを追加します。
// add type map entry to map SQL type // "EMPLOYEE" to Java type "EmployeeObj" Map map = conn.getTypeMap(); map.put("EMPLOYEE", Class.forName("EmployeeObj"));
次に、EMPLOYEE_LIST
からSQL EMPLOYEE
オブジェクトを取り出します。この操作をするには、employeeArray
配列オブジェクトのgetArray
メソッドをコールします。このメソッドにより、オブジェクト配列が戻されます。getArray
メソッドでは、employees
オブジェクト配列にEMPLOYEE
オブジェクトが戻されます。
// Retrieve array elements Object[] employees = (Object[]) employeeArray.getArray();
最後にループを作成して、各EMPLOYEE
SQLオブジェクトに、EmployeeObj
Javaオブジェクトのemp
を割り当てます。
// Each array element is mapped to EmployeeObj object. for (int i=0; i<employees.length; i++) { EmployeeObj emp = (EmployeeObj) employees[i]; ... }