この章では、Java配列とそのデータにマップされるOracleコレクションにアクセスして操作するための、標準Java Database Connectivity(JDBC)に対するOracleの拡張機能について説明します。内容は次のとおりです。
データベース内の変数配列(VARRAY)またはNESTED TABLEのいずれかであるOracleコレクションは、Javaでは配列にマップされます。JDBC 2.0配列は、JavaでOracleコレクションをインスタンス化するために使用されます。コレクションおよび配列という用語は、どちらも同じ意味で使用されることがあります。ただし、データベース側ではコレクション、JDBCアプリケーション側では配列のほうが適切です。
サポートされるのは、SQL型名を指定することでコレクションの型を記述できる、名前付きコレクションのみです。JDBCを使用すると、次のものに配列を使用できます。
SELECT
句の列
IN
またはOUT
バインド変数
Oracleオブジェクトの属性
他の配列の要素
この項の内容は次のとおりです。
アプリケーションでは、弱い型指定のoracle.sql.ARRAY
クラスのインスタンスとして、または事前に作成した強い型指定のカスタムJavaクラスのインスタンスとしてコレクションをインスタンス化するオプションがあります。コレクションのために使用するカスタムJavaクラスは、カスタム・コレクション・クラスと呼びます。カスタム・コレクション・クラスは、Oracleのoracle.sql.ORAData
インタフェースを実装する必要があります。さらに、カスタム・クラスまたはコンパニオン・クラスは、oracle.sql.ORADataFactory
を実装する必要があります。標準java.sql.SQLData
インタフェースは、SQLオブジェクト型のマッピング専用です。
oracle.sql.ARRAY
クラスは、標準のjava.sql.Array
インタフェースを実装します。
ARRAY
クラスには、配列全体を取り出し、配列要素のサブセットを取り出し、配列要素のSQLベース型名を取り出すための機能があります。ただし、setterメソッドがないため、配列に書き込むことはできません。
カスタム・コレクション・クラスを使用すると、ARRAY
クラスと同様に、配列のすべてまたは一部を取得して、SQLベース型名を取得できます。強い型指定により、実行時まで検出できない可能性のあるコーディング・エラーを、コンパイル時に発見できる利点もあります。
また、JPublisherによって作成されるカスタム・コレクション・クラスは、個々にアクセス可能な要素によって、書込み可能な機能を提供します。
注意: VARRAYへのアクセスとNESTED TABLEへのアクセス間で、コード上の違いはありません。ARRAY クラス・メソッドは、VARRAYまたはNESTED TABLEに適用されているかどうかを判断し、適切なアクションを決定して応答します。 |
Oracleは名前付きコレクションのみをサポートしているため、特定のVARRAY
型名またはNESTED TABLE型名を制限する必要があります。VARRAYとNESTED TABLEは、型自体ではなく型のカテゴリです。
次のSQL CREATE TYPE
文を使用してコレクションを作成すると、コレクションにSQL型名が割り当てられます。
CREATE TYPE <sql_type_name> AS <datatype>;
VARRAYは、サイズ可変の配列です。順序付けられたデータ要素のセットを保持し、要素はすべて同じデータ型です。各要素は、索引を持ちますが、これはVARREYにおける要素の位置に対応する番号です。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
を指定しています。
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
マルチ・レベルのコレクション型を作成すると、実表の列またはオブジェクト型の属性として使用できます。
結果セットまたはコール可能文によって配列インスタンス内のコレクション・データを取得し、プリコンパイルされたSQL文またはコール可能文内のバインド変数として戻すことができます。
標準java.sql.Array
インタフェースを実装するoracle.sql.ARRAY
クラスは、Oracleコレクションのデータにアクセスし、更新するために必要な機能を提供します。
この項では、配列のgetterメソッドとsetterメソッドについて説明します。Java配列としてコレクションを取り出し、渡すには、次の結果セット、コール可能文およびプリコンパイルされたSQL文メソッドを使用します。
結果セットおよびコール可能文のgetterメソッド
OracleResultSet
クラスとOracleCallableStatement
クラスは、出力パラメータとして、つまりoracle.sql.ARRAY
インスタンスまたはjava.sql.Array
インスタンスとしてARRAY
オブジェクトを取り出すために、getARRAY()
メソッドとgetArray()
メソッドをサポートします。getObject
メソッドも使用できます。これらのメソッドは、入力としてString
列名またはint
列索引を取ります。
プリコンパイルされたSQL文およびコール可能文のsetterメソッド
OraclePreparedStatement
クラスとOracleCallableStatement
クラスは、更新されたARRAY
オブジェクトをバインド変数として取ってデータベースに渡すsetARRAY
メソッドとsetArray
メソッドをサポートします。setObject
メソッドも使用できます。これらのメソッドは、oracle.sql.ARRAY
インスタンスまたはjava.sql.Array
インスタンスに加えて、String
パラメータ名またはint
パラメータ索引を入力として取ります。
この項の内容は次のとおりです。
oracle.sql.ARRAY
クラスには、配列要素をJavaプリミティブ型として戻すメソッドが含まれています。これらのメソッドを使用すると、Datum
インスタンスとしてコレクション要素にアクセスしてからDatum
インスタンスをJavaプリミティブ型に変換する方法に比べ、より容易にコレクション要素にアクセスできます。
注意: oracle.sql.ARRAY クラスのこれらの特殊なメソッドは、数値コレクションに制限されます。 |
最初のシグネチャを使用している各メソッドは、コレクション要素をXXX
[]
の形式で戻します。ここで、XXX
はJavaプリミティブ型です。第2のシグネチャを使用している各メソッドは、count
によって指定される数の要素を含んでいて、index
の場所で開始されるコレクションのスライスを戻します。
Oracle JDBCドライバには、ARRAY
の内容のバッファリングを有効または無効にするためのパブリック・メソッドが用意されています。
oracle.sql.ARRAY
クラスには、次のメソッドがあります。
ARRAY
要素にgetAttributes
およびgetArray
の各メソッドで複数回アクセスし、ARRAY
データがオーバーフローせずにJava仮想マシン(JVM)のメモリーに格納されると想定する場合は、JDBCアプリケーションで自動バッファリングを有効にすることをお薦めします。
重要: 変換した要素をバッファリングすると、JDBCアプリケーションでは、大量のメモリーが消費されます。 |
自動バッファリングを有効にすると、oracle.sql.ARRAY
オブジェクトでは、変換したすべての要素のローカルのコピーが保持されます。このデータが保持されるため、この情報に2回目にアクセスするときにはデータ・フォーマット変換処理を実行しなくて済みます。
この項では、配列オブジェクトを作成する方法と、配列オブジェクトとしてコレクションを取り出し、渡す方法について説明します。内容は次のとおりです。
注意: Oracle JDBCでは、java.sql.Connection インタフェースのJDBC 4.0のcreateArrayOf メソッドはサポートされていません。Oracleの配列型はすべて名前付きですが、このメソッドでは匿名の配列型のみが許容されています。かわりにOracle固有のメソッド、oracle.jdbc.OracleConnection.createARRAY を使用してください。 |
この項では、ARRAY
オブジェクトを作成する方法について説明します。この項の内容は次のとおりです。
ARRAYオブジェクトの作成に関する手順
Oracle Database 11gリリース1(11.1)以降、oracle.jdbc.OracleConnection
インタフェースのcreateARRAY
ファクトリ・メソッドを使用して配列オブジェクトを作成することができます。配列を作成するファクトリ・メソッドは次のように定義されています。
public ARRAY createARRAY(java.lang.String typeName,java.lang.Object elements)throws SQLException
ここで、typeName
は、作成されたオブジェクトのSQL型の名前で、elements
は作成されたオブジェクトの要素です。
CREATE
TYPE
文を使用して、次のようにコレクションを作成します。
CREATE TYPE elements AS varray(22) OF NUMBER(5,2);
elements
の内容は、次の2つの場合があります。
Javaプリミティブ形の配列。たとえば、int[]
です。
xxx
[]
などのJavaオブジェクトの配列。ここで、xxx
はJavaクラスの名前です。たとえば、Integer[]
です。
配列のユーザー定義SQL型名を指定しているJava文字列、および配列に含まれる個別の要素が含まれているJavaオブジェクトを渡すことによって、ARRAY
オブジェクトを構築します。
ARRAY array = oracle.jdbc.OracleConnection.createARRAY(sql_type_name, elements);
マルチ・レベル・コレクションの作成
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);
この項では、結果セットからARRAY
インスタンス全体を取り出す方法を最初に説明し、次にARRAY
インスタンスから要素を取り出す方法について説明します。この項の内容は次のとおりです。
oracle.sql.ARRAY
オブジェクトを戻すgetARRAY
メソッドを使用して、結果セットをOracleResultSet
オブジェクトにキャストすることで、SQL配列を結果セットから取り出すことができます。結果セットをキャストするのを避けるには、java.sql.ResultSet
インタフェースによって指定された標準のgetObject
メソッドを使用してデータを取得し、その出力をoracle.sql.ARRAY
にキャストします。
ARRAY
オブジェクトを作成した後は、次に示すoracle.sql.ARRAY
クラスの3つのオーバーロード・メソッドのいずれかを使用して、データを取り出すことができます。
Oracleは配列のすべての要素、またはサブセットを取り出すことができるメソッドも提供しています。
注意: 構造化オブジェクトの配列を操作している場合は、Oracleは、オブジェクトをJavaにマップする方法を選択できるように、型マップを指定できる次の3つのメソッドのバージョンを提供します。 |
getOracleArray
getOracleArray()
メソッドは、標準Array
インタフェースでは指定されていないOracle固有の拡張機能です。getOracleArray
メソッドでは、配列の要素値を取り出してDatum[]
配列に格納します。この要素は、元の配列のSQL型データに対応するoracle.sql.*
データ型です。
構造化オブジェクトの配列では、このメソッドは要素のためにoracle.sql.STRUCT
インスタンスを使用します。
また、getOracleArray(
index
,
count
)
メソッドを使用すると、配列要素のサブセットを取得できます。
getResultSet
getResultSet
メソッドは、ARRAY
オブジェクトによって示される配列の要素が含まれる結果セットを戻します。結果セットには、1つの配列要素ごとに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
)
メソッドを使用すると、配列要素のサブセットを取り出すことができます。
配列要素を戻すために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 を使用するとパフォーマンスに影響を与える可能性があり、数値のコレクションの場合は推奨されません。 |
デフォルトでは、構造化オブジェクトの要素を持つ配列を操作しているときに、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.sql.STRUCT
オブジェクトとして戻されます。
getResultSet(
map
)
メソッドは、getArray(
map
)
メソッドと同じように動作します。
配列の内容全体を取り出さない場合は、サブセットを取り出すことができる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
オブジェクトを表します。
注意: 配列全体ではなく、配列のサブセットを取り出すことにパフォーマンス上の利点はありません。 |
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)); }
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 ();
この項では、プリコンパイルされたSQL文オブジェクトまたはコール可能文オブジェクトに配列を渡す方法について説明します。
配列のプリコンパイルされたSQL文への引渡し
次の手順に従って、配列をプリコンパイルされたSQL文に渡します。
注意: 配列は、IN またはOUT バインド変数として使用できます。 |
プリコンパイルされたSQL文に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
オブジェクトを作成します。
プリコンパイルされたSQL文をOraclePreparedStatement
にキャストし、setARRAY()
を使用して、プリコンパイルされたSQL文に配列を渡します。
(OraclePreparedStatement)stmt.setARRAY(parameterIndex, array);
parameterIndex
はパラメータ索引を表し、array
は手順2で作成したoracle.sql.ARRAY
オブジェクトを表します。
プリコンパイルされたSQL文を実行します。
配列のコール可能文への引渡し
コレクションをPL/SQLブロックのOUT
パラメータとして取り出すには、次の手順を実行してOUT
パラメータのバインド型を登録します。
次のように、コール可能文をOracleCallableStatement
にキャストします。
OracleCallableStatement ocs = (OracleCallableStatement)conn.prepareCall("{? = call func()}");
次の形式のregisterOutParameter
メソッドを使用して、OUT
パラメータを登録します。
ocs.registerOutParameter (int param_index, int sql_type, string sql_type_name);
param_index
はパラメータ索引、sql_type
はSQL型コード、sql_type_name
は配列型の名前です。この場合、sql_type
はOracleTypes.ARRAY
です。
次のように、コールを実行します。
ocs.execute();
次のように、値を取得します。
oracle.sql.ARRAY array = ocs.getARRAY(1);
配列にOracleオブジェクトが含まれる場合は、型マップを使用して、配列のオブジェクトを、対応するJavaクラスに関連付けることができます。型マップを指定しない場合または型マップに特定のOracleオブジェクトのエントリが含まれない場合は、oracle.sql.STRUCT
オブジェクトとして各要素が戻されます。
型マップを使用して、配列の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('Scott Tiger', 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]; ... }
この項では、主にoracle.sql.ARRAY
クラスの機能について説明しています。ただし、カスタムJavaクラス、より厳密にはカスタム・コレクション・クラスからも、Oracleコレクションにアクセスできます。
カスタム・コレクション・クラスは自分で作成できますが、Oracle JPublisherユーティリティを使用するのが最も便利な方法です。JPublisherによって生成されるカスタム・コレクション・クラスには、この章で前述したすべての機能に加えて、次の利点があります。
カスタム・コレクション・クラスは、強い型指定です。この強い型指定により、実行時まで検出できないコーディング・エラーを、コンパイル時に発見できます。
カスタム・コレクション・クラスは変更できます(可変)。JPublisherによって作成されるカスタム・コレクション・クラスでは、ARRAY
クラスとは異なり、getElement
メソッドとsetElement
メソッドを使用して個々の要素を取得および設定できます。
カスタム・コレクション・クラスは、次の3つの要件を満たす必要があります。
oracle.sql.ORAData
インタフェースを実装する必要があります。カスタム・オブジェクト・クラスにかわる標準JDBC SQLData
インタフェースは、カスタム・コレクション・クラス用ではないことに注意してください。
このクラスまたはコンパニオン・クラスで、カスタム・コレクション・クラスのインスタンスを作成するには、oracle.sql.ORADataFactory
インタフェースを実装する必要があります。
コレクション・データを格納する手段が必要です。一般に、この目的のためにoracle.sql.ARRAY
属性が直接または間接的に挿入されます。
JPublisherによって作成されるカスタム・コレクション・クラスは、ORAData
とORADataFactory
を実装し、oracle.sql.ARRAY
属性を間接的に挿入します。生成されたカスタム・コレクション・クラスは、oracle.jpub.runtime.MutableArray
属性を持ちます。MutableArray
クラスは、oracle.sql.ARRAY
属性を持ちます。
注意: JPublisherを使用してカスタム・コレクション・クラスを作成する場合は、ORAData 実装を使用する必要があります。これは、JPublisher -usertypes マッピング・オプションが、デフォルトのoracle に設定されている場合に当てはまります。
カスタム・コレクション・クラスでは |
強い型指定のカスタム・コレクション・クラスの例として、OracleコレクションMYVARRAY
を定義する場合は、JPublisherはMyVarray
カスタム・コレクション・クラスを作成できます。汎用oracle.sql.ARRAY
インスタンスのかわりにMyVarray
インスタンスを使用すると、実行時ではなくコンパイル時のエラーを簡単に捕捉できます。たとえば、MyVarray
変数に別の種類の配列を間違えて割り当てた場合は、簡単にエラーが検出されます。
カスタム・コレクション・クラスを使用しない場合は、コレクションをマップするために標準java.sql.Array
インスタンス、またはoracle.sql.ARRAY
インスタンスを使用します。