ヘッダーをスキップ
Oracle® Database JDBC開発者ガイド
12cリリース1 (12.1)
B71308-02
  目次へ移動
目次
索引へ移動
索引

前
 
次
 

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インタフェースの詳細は、My Oracle Supportノート1364193.1を参照してください。

コレクションのための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.jdbc.OracleDataインタフェースを実装する必要があります。さらに、カスタム・クラスまたはコンパニオン・クラスは、oracle.jdbc.OracleDataFactoryを実装する必要があります。標準java.sql.SQLDataインタフェースは、SQLオブジェクト型のマッピング専用です。

oracle.sql.ARRAYクラスは、標準のjava.sql.Arrayインタフェースを実装します。

ARRAYクラスには、配列全体を取り出し、配列要素のサブセットを取り出し、配列要素のSQLベース型名を取り出すための機能があります。ただし、setterメソッドがないため、配列に書き込むことはできません。

カスタム・コレクション・クラスを使用すると、ARRAYクラスと同様に、配列のすべてまたは一部を取得して、SQLベース型名を取得できます。強い型指定により、実行時まで検出できない可能性のあるコーディング・エラーを、コンパイル時に発見できる利点もあります。

また、JPublisherによって作成されるカスタム・コレクション・クラスは、個々にアクセス可能な要素によって、書込み可能な機能を提供します。


注意:

VARRAYへのアクセスとNESTED TABLEへのアクセス間で、コード上の違いはありません。ARRAYクラス・メソッドは、VARRAYまたはNESTED TABLEに適用されているかどうかを判断し、適切なアクションを決定して応答します。


関連項目:

カスタム・コレクション・クラスの詳細は、「JPublisherで生成するカスタム・コレクション・クラス」を参照してください。

コレクションの作成

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を指定しています。

マルチ・レベルのコレクション型の作成

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文メソッドを使用します。


注意:

Oracle Database 12cリリース1 (12.1)以降、oracle.sql.ARRAYクラスは非推奨となり、oracle.jdbc.OracleArrayインタフェースに置き換えられています。このインタフェースはoracle.jdbcパッケージに属します。標準互換性には(可能であれば)java.sqlパッケージの使用可能なメソッドを使用し、Oracle固有の拡張機能にはoracle.jdbcパッケージの使用可能なメソッドを使用することをお薦めします。oracle.jdbc.OracleArrayインタフェースの詳細は、My Oracle Supportノート1364193.1を参照してください。

結果セットおよびコール可能文の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パラメータ索引を入力として取ります。

ARRAYパフォーマンス拡張要素メソッド

この項の内容は次のとおりです。

Javaプリミティブ型の配列としてのoracle.sql.ARRAY要素へのアクセス

oracle.sql.ARRAYクラスには、配列要素をJavaプリミティブ型として戻すメソッドが含まれています。これらのメソッドを使用すると、Datumインスタンスとしてコレクション要素にアクセスしてからDatumインスタンスをJavaプリミティブ型に変換する方法に比べ、より容易にコレクション要素にアクセスできます。


注意:

oracle.sql.ARRAYクラスのこれらの特殊なメソッドは、数値コレクションに制限されます。

最初のシグネチャを使用している各メソッドは、コレクション要素をXXX[]の形式で戻します。ここで、XXXはJavaプリミティブ型です。第2のシグネチャを使用している各メソッドは、countによって指定される数の要素を含んでいて、indexの場所で開始されるコレクションのスライスを戻します。

ARRAY自動要素バッファリング

Oracle JDBCドライバには、ARRAYの内容のバッファリングを有効または無効にするためのパブリック・メソッドが用意されています。

oracle.sql.ARRAYクラスには、次のメソッドがあります。

  • setAutoBuffering

  • getAutoBuffering

ARRAY要素にgetAttributesおよびgetArrayの各メソッドで複数回アクセスし、ARRAYデータがオーバーフローせずにJava仮想マシン(JVM)のメモリーに格納されると想定する場合は、JDBCアプリケーションで自動バッファリングを有効にすることをお薦めします。


重要:

変換した要素をバッファリングすると、JDBCアプリケーションでは、大量のメモリーが消費されます。

自動バッファリングを有効にすると、oracle.sql.ARRAYオブジェクトでは、変換したすべての要素のローカルのコピーが保持されます。このデータが保持されるため、この情報に2回目にアクセスするときにはデータ・フォーマット変換処理を実行しなくて済みます。

ARRAY自動索引作成

配列を自動索引作成モードにすると、配列オブジェクトは配列要素へのアクセスを迅速に行うために索引表をメンテナンスします。

oracle.sql.ARRAYクラスには、自動配列索引作成をサポートする次のメソッドが含まれています。

  • setAutoIndexing

  • setAutoIndexing

デフォルトでは、自動索引作成は有効にされていません。JDBCアプリケーションで、getArrayおよびgetResultSetの各メソッドを使用して配列要素のランダム・アクセスを実行する場合は、ARRAYオブジェクトの自動索引作成を有効にします。

配列の作成と使用方法

この項では、配列オブジェクトを作成する方法と、配列オブジェクトとしてコレクションを取り出し、渡す方法について説明します。内容は次のとおりです。

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は作成されたオブジェクトの要素です。

配列を作成するには次の操作を実行します。

  1. CREATE TYPE文を使用して、次のようにコレクションを作成します。

    CREATE TYPE elements AS varray(22) OF NUMBER(5,2);
    

    elementsの内容は、次の2つの場合があります。

    • Javaプリミティブ形の配列。たとえば、int[]です。

    • xxx[]などのJavaオブジェクトの配列。ここで、xxxはJavaクラスの名前です。たとえば、Integer[]です。

  2. 配列のユーザー定義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つのオーバーロード・メソッドのいずれかを使用して、データを取り出すことができます。

  • 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つの配列要素ごとに1つの行があり、各行には2つの列があります。最初の列には、配列内でその要素を参照する索引が格納され、2つめの列には要素値が格納されます。VARRAYの場合、索引は配列内での要素の位置を表します。定義上、順序付けられていないネスト表の場合、索引は特定の問合せにおける要素の戻り順のみを反映します。

NESTED TABLEからデータを取り出すときは、getResultSetを使用することをお薦めします。NESTED TABLEの要素数には、制限はありません。メソッドから戻されたResultSetオブジェクトのポインタの初期値は、データの第1行です。nextメソッドおよび適切なgetXXXメソッドを使用すると、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();

ここで、intArrayoracle.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);

この例のobjArrayoracle.sql.ARRAYオブジェクトを表し、mapjava.util.Mapオブジェクトを表します。

型マップに特定のOracleオブジェクトに対応するエントリが含まれない場合、要素はoracle.jdbc.OracleStructオブジェクトとして戻されます。

getResultSet(map)メソッドは、getArray(map)メソッドと同じように動作します。

配列要素のサブセットの取出し

配列の内容全体を取り出さない場合は、サブセットを取り出すことができるgetArraygetResultSetおよび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);

arroracle.sql.ARRAYオブジェクト、indexlong型、countint型、mapjava.util.Mapオブジェクトを表します。


注意:

配列全体ではなく、配列のサブセットを取り出すことにパフォーマンス上の利点はありません。

oracle.sql.Datum配列への配列要素の取出し

oracle.sql.Datum[]配列を戻すには、getOracleArrayを使用します。戻される配列の要素は、元の配列要素のSQLデータ型に対応するoracle.sql.*型です。たとえば、次のようになります。

Datum arraydata[] = arr.getOracleArray();

arroracle.sql.ARRAYオブジェクトを表します。

次の例は、接続オブジェクトconnおよび文オブジェクトstmtがすでに作成済であることを前提としています。この例では、SQL型名NUM_ARRAYの配列がNUMBERデータのVARRAYを格納するために作成されます。NUM_ARRAYは、表VARRAY_TABLEに格納されます。

問合せは、VARRAY_TABLEの内容を選択します。結果セットはOracleResultSetにキャストされます。それに対してgetARRAYメソッドが適用され、配列データがmy_arrayに取得されます。これはoracle.sql.ARRAYオブジェクトです。

my_arrayoracle.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クラスのgetObjectgetARRAYまたはgetArrayメソッドを使用して、oracle.sql.ARRAYのインスタンスとしてコレクション要素にアクセスします。

次のコードは、getOracleArraygetArrayおよび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バインド変数として使用できます。

  1. プリコンパイルされたSQL文にoracle.sql.ARRAYオブジェクトとして渡す配列を定義します。

    ARRAY array = oracle.jdbc.OracleConnection.createARRAY(sql_type_name, elements);
    

    sql_type_nameは配列のユーザー定義SQL型名を指定するJava文字列を表し、elementsは要素のJava配列を含むjava.lang.Objectを表します。

  2. 実行するSQL文を含むjava.sql.PreparedStatementオブジェクトを作成します。

  3. プリコンパイルされたSQL文をOraclePreparedStatementにキャストし、setARRAY()を使用して、プリコンパイルされたSQL文に配列を渡します。

    (OraclePreparedStatement)stmt.setARRAY(parameterIndex, array);
    

    parameterIndexはパラメータ索引を表し、arrayは手順2で作成したoracle.sql.ARRAYオブジェクトを表します。

  4. プリコンパイルされたSQL文を実行します。

配列のコール可能文への引渡し

コレクションをPL/SQLブロックのOUTパラメータとして取り出すには、次の手順を実行してOUTパラメータのバインド型を登録します。

  1. 次のように、コール可能文をOracleCallableStatementにキャストします。

    OracleCallableStatement ocs = (OracleCallableStatement)conn.prepareCall("{? = call func()}");
    
  2. 次の形式のregisterOutParameterメソッドを使用して、OUTパラメータを登録します。

    ocs.registerOutParameter
            (int param_index, int sql_type, string sql_type_name);
    

    param_indexはパラメータ索引、sql_typeはSQL型コード、sql_type_nameは配列型の名前です。この場合、sql_typeOracleTypes.ARRAYです。

  3. 次のように、コールを実行します。

    ocs.execute();
    
  4. 次のように、値を取得します。

    oracle.sql.ARRAY array = ocs.getARRAY(1);
    

型マップを使用した配列要素のマップ

配列にOracleオブジェクトが含まれる場合は、型マップを使用して、配列のオブジェクトを、対応するJavaクラスに関連付けることができます。型マップを指定しない場合または型マップに特定のOracleオブジェクトのエントリが含まれない場合、各要素はoracle.jdbc.OracleStructオブジェクトとして戻されます。

型マップを使用して、配列のOracleオブジェクトと対応するJavaクラスとのマッピングを決定するときは、マップに適切なエントリを追加する必要があります。

次の例では、型マップを使用して配列要素をカスタムJavaオブジェクト・クラスにマップする方法を説明します。この例の配列は、NESTED TABLEです。この例では、まず、名前属性と従業員番号属性が設定されているEMPLOYEEオブジェクトを定義します。EMPLOYEE_LISTEMPLOYEEオブジェクトの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_LISTARRAYオブジェクト(次の例では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];
   ...
}

JPublisherで生成するカスタム・コレクション・クラス

この項では、主にoracle.sql.ARRAYクラスの機能について説明しています。ただし、カスタムJavaクラス、より厳密にはカスタム・コレクション・クラスからも、Oracleコレクションにアクセスできます。

カスタム・コレクション・クラスは自分で作成できますが、Oracle JPublisherユーティリティを使用するのが最も便利な方法です。JPublisherによって生成されるカスタム・コレクション・クラスには、この章で前述したすべての機能に加えて、次の利点があります。

  • カスタム・コレクション・クラスは、強い型指定です。この強い型指定により、実行時まで検出できないコーディング・エラーを、コンパイル時に発見できます。

  • カスタム・コレクション・クラスは変更できます(可変)。JPublisherによって作成されるカスタム・コレクション・クラスでは、ARRAYクラスとは異なり、getElementメソッドとsetElementメソッドを使用して個々の要素を取得および設定できます。

カスタム・コレクション・クラスは、次の3つの要件を満たす必要があります。

  • oracle.jdbc.OracleDataインタフェースを実装する必要があります。カスタム・オブジェクト・クラスにかわる標準JDBC SQLDataインタフェースは、カスタム・コレクション・クラス用ではないことに注意してください。

  • このクラスまたはコンパニオン・クラスで、カスタム・コレクション・クラスのインスタンスを作成するには、oracle.jdbc.OracleDataFactoryインタフェースを実装する必要があります。

  • コレクション・データを格納する手段が必要です。一般に、この目的のためにoracle.sql.ARRAY属性が直接または間接的に挿入されます。

JPublisherによって作成されるカスタム・コレクション・クラスは、OracleDataOracleDataFactoryを実装し、oracle.sql.ARRAY属性を間接的に挿入します。生成されたカスタム・コレクション・クラスは、oracle.jpub.runtime.MutableArray属性を持ちます。MutableArrayクラスは、oracle.sql.ARRAY属性を持ちます。


注意:

JPublisherを使用してカスタム・コレクション・クラスを作成する場合は、OracleData実装を使用する必要があります。これは、JPublisher -usertypesマッピング・オプションが、デフォルトのoracleに設定されている場合に当てはまります。

カスタム・コレクション・クラスではSQLData実装を使用できません。-usertypesマッピング・オプションをjdbcに設定することは無効です。


強い型指定のカスタム・コレクション・クラスの例として、OracleコレクションMYVARRAYを定義する場合は、JPublisherはMyVarrayカスタム・コレクション・クラスを作成できます。汎用oracle.sql.ARRAYインスタンスのかわりにMyVarrayインスタンスを使用すると、実行時ではなくコンパイル時のエラーを簡単に捕捉できます。たとえば、MyVarray変数に別の種類の配列を間違えて割り当てた場合は、簡単にエラーが検出されます。

カスタム・コレクション・クラスを使用しない場合は、コレクションをマップするために標準java.sql.Arrayインスタンス、またはoracle.sql.ARRAYインスタンスを使用します。


関連項目: