この章では、オブジェクト参照へのアクセスおよび操作を行う、標準Java Database Connectivity(JDBC)に対するOracle拡張機能について説明します。次の項目が含まれます。
Oracleでは、データベース・オブジェクトへの参照を使用できます。Oracle JDBCでは、次のオブジェクト参照がサポートされます。
SELECT
句の列
IN
またはOUT
バインド変数
Oracleオブジェクトの属性
コレクション型オブジェクトの要素
SQLでは、オブジェクト参照(REF
)は厳密に型指定されています。たとえば、EMPLOYEE
オブジェクトへの参照は、REF
のみではなく、EMPLOYEE REF
として定義されます。
Oracle JDBCでオブジェクト参照を選択するときには、オブジェクトそのものではなく、オブジェクトへのポインタのみが取り出されることに注意してください。参照は、弱い型指定のoracle.sql.REF
インスタンス、または移植性の高いjava.sql.Ref
インスタンスとしてインスタンス化することも、強い型指定の作成済カスタムJavaクラスのインスタンスとしてインスタンス化することもできます。オブジェクト参照に使用するカスタムJavaクラスを、カスタム参照クラスと呼びます。このクラスは、oracle.sql.ORAData
インタフェースを実装する必要があります。oracle.sql.REF
クラスは、標準のjava.sql.Ref
インタフェースを実装します。
REF
インスタンスは、結果セットまたはコール可能文オブジェクトから取り出せます。更新されたREF
インスタンスは、プリコンパイルされたSQL文またはコール可能文オブジェクトで、データベースに戻せます。REF
クラスには、基礎となるオブジェクト属性値を取り出して設定する機能や、基礎となるオブジェクトのSQLベース型名を取り出す機能が含まれています。
カスタム参照クラスには、これと同じ機能が含まれている他に、強い型指定が適用されるという利点があります。この強い型指定により、実行時まで検出できないコーディング・エラーを、コンパイル時に発見できます。
注意:
|
オブジェクト参照からオブジェクト・データにアクセスし、更新するには、結果セットまたはコール可能文から参照インスタンスを取出し、プリコンパイルされたSQL文またはコール可能文のバインド変数に渡す必要があります。オブジェクト属性へのアクセスおよび更新を行う機能は、参照インスタンスに含まれています。
この項には、次の項目が含まれます。
結果セット、コール可能文およびプリコンパイルされたSQL文のメソッドを使用して、オブジェクト参照の取出しおよび引渡しができます。
結果セットおよびコール可能文のgetterメソッド
OracleResultSet
およびOracleCallableStatement
クラスは、REF
オブジェクトを出力パラメータとして取り出すgetREF
およびgetRef
メソッドをサポートします。REF
オブジェクトは、oracle.sql.REF
インスタンスまたはjava.sql.Ref
インスタンスとして取り出すことができます。getObject
メソッドも使用できます。これらのメソッドは、入力としてString
列名またはint
列索引を取ります。
プリコンパイルされたSQL文およびコール可能文のsetterメソッド
OraclePreparedStatement
およびOracleCallableStatement
クラスは、REF
オブジェクトをバインド変数として取り、データベースに渡す、setREF
およびsetRef
メソッドをサポートします。setObject
メソッドも使用できます。これらのメソッドは、入力としてString
パラメータ名またはint
パラメータ索引を取ります。同時に、oracle.sql.REF
インスタンスまたはjava.sql.Ref
インスタンスも取ります。
次のoracle.sql.REF
クラス・メソッドを使用して、SQLオブジェクト型名の取出しや、基礎となるオブジェクト・データの取出しおよび引渡しを行います。
参照オブジェクトの完全修飾SQL構造化型名を取り出します。これは、java.sql.Ref
インタフェースで指定される標準メソッドです。
参照オブジェクトをデータベースから取り出し、属性値にアクセスできるようにします。オプションで、型マップ・オブジェクトを取ることができます。また、データベース接続オブジェクトのデフォルト型マップを使用できます。このメソッドはOracle拡張機能です。
参照オブジェクトをデータベースに設定し、属性値を更新できるようにします。入力として、オブジェクト型のインスタンス(STRUCT
インスタンスまたはカスタム・オブジェクト・クラスのインスタンス)を取ります。このメソッドはOracle拡張機能です。
この項では、オブジェクト参照の取出しと引渡しを行うJDBC機能を説明します。次の項目が含まれます。
オブジェクト参照を取り出す方法を示すために、次の例では、最初に、Oracleオブジェクト型ADDRESS
を定義し、次にPEOPLE
表でこのオブジェクト型を参照します。
create type ADDRESS as object (street_name VARCHAR2(30), house_no NUMBER); create table PEOPLE (col1 VARCHAR2(30), col2 NUMBER, col3 REF ADDRESS);
ADDRESS
オブジェクト型には、street nameとhouse numberという2つの属性があります。PEOPLE
表には、文字データ用の列、数値データ用の列、およびADDRESS
オブジェクトへの参照を含む列が設定されています。
オブジェクト参照を取り出すには、次の手順に従ってください。
Address
をSQLオブジェクト型のADDRESS
に対応するJavaカスタム・クラスに変換します。
JavaクラスAddress
とSQL型ADDRESS
間の対応を、型マップに追加します。
また、PEOPLE
データベース表の定義については、この項の始めの説明を参照してください。前述の手順を実行するコードは、Address
を型マップに追加する手順を除いて、次のようになります。
ResultSet rs = stmt.executeQuery("SELECT col3 FROM PEOPLE"); while (rs.next()) { REF ref = ((OracleResultSet)rs).getREF(1); Address a = (Address)ref.getValue(); }
注意: 前述のコードで、stmt はあらかじめ定義されている文オブジェクトです。 |
他のSQL型と同様に、結果セットのgetObject
メソッドを使用して参照を取り出すことができます。この場合、出力をキャストする必要があります。たとえば、次のようになります。
REF ref = (REF)rs.getObject(1);
getREF
のかわりにgetObject
を使用しても、パフォーマンスは向上しません。ただし、getREF
を使用すると、出力をキャストする必要がありません。
オブジェクト参照を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
は、この参照が使用される構造化オブジェクト型の名前です。たとえば、OUT
パラメータがADDRESS
オブジェクトに対する参照の場合、ADDRESS
は渡されるsql_type_name
です。
次のように、コールを実行します。
ocs.execute();
オブジェクト参照をプリコンパイルされたSQL文に渡す方法は、他のSQL型を渡す場合と同様です。プリコンパイルされたSQL文のオブジェクトのsetObject
メソッドまたはsetREF
メソッドを使用します。
次のプリコンパイルされたSQL文を使用し、ROWID
に基づいてアドレス参照を更新します。
PreparedStatement pstmt = conn.prepareStatement ("update PEOPLE set ADDR_REF = ? where ROWID = ?"); ((OraclePreparedStatement)pstmt).setREF (1, addr_ref); ((OraclePreparedStatement)pstmt).setROWID (2, rowid);
REF
オブジェクトのsetValue
メソッドを使用すると、データベースにあるオブジェクトの値をオブジェクト参照から更新できます。このためには、最初に、データベース・オブジェクトに対する参照を取り出し、データベース・オブジェクトに対応するJavaオブジェクトを作成する必要があります。
たとえば、次のように、「オブジェクト参照の取出しと引渡し」のコードを使用して、データベースのADDRESS
オブジェクトへの参照を取り出せます。
ResultSet rs = stmt.executeQuery("SELECT col3 FROM PEOPLE"); if (rs.next()) { REF ref = rs.getREF(1); Address a = (Address)ref.getValue(); }
次に、データベースのADDRESS
オブジェクトに対応するJavaのAddress
オブジェクトを作成できます。次のように、REF
クラスのsetValue
メソッドを使用して、データベース・オブジェクトの値を設定します。
Address addr = new Address(...); ref.setValue(addr);
この例では、setValue
メソッドによりデータベースのADDRESS
オブジェクトが即時更新されます。
この章では、oracle.sql.REF
クラスの機能を主に説明していますが、カスタムJavaクラス、より厳密にはカスタム参照クラスからも、Oracleオブジェクト参照にアクセスできます。
カスタム参照クラスは、この章で説明した機能をすべて提供します。それに加え、強い型指定が適用されるという利点があります。カスタム参照クラスは、次の3つの要件を満たす必要があります。
oracle.sql.ORAData
インタフェースを実装する必要があります。カスタム・オブジェクト・クラス用の代替である標準JDBC SQLData
インタフェースは、カスタム参照クラスには使用できないので注意してください。
コンパニオン・クラスの場合は、カスタム参照クラスのインスタンスを作成するために、oracle.sql.ORADataFactory
インタフェースを実装する必要があります。
オブジェクト・データを参照する方法を用意する必要があります。JPublisherは、oracle.sql.REF
属性を使用することにより、これを実現します。
カスタム参照クラスは独自に作成できますが、Oracle JPublisherユーティリティで作成すると便利です。JPublisherを使用してOracleオブジェクトにマップするカスタム・オブジェクト・クラスを生成し、ORAData
実装を使用するように指定すると、JPublisherはORAData
とORADataFactory
を実装し、oracle.sql.REF
属性を含むカスタム参照クラスも生成します。ORAData
実装は、JPublisherの-usertypes
マッピング・オプションにoracle
が設定されている場合に使用されます。これがデフォルトです。
カスタム参照クラスは、強い型指定です。たとえば、OracleオブジェクトEMPLOYEE
を定義すると、JPublisherによりEmployee
カスタム・オブジェクト・クラスおよびEmployeeRef
カスタム参照クラスが生成されます。汎用oracle.sql.REF
インスタンスのかわりにEmployeeRef
インスタンスを使用すると、実行時ではなくコンパイル時にエラーを簡単に捕捉できます。たとえば、EmployeeRef
変数に別の種類のオブジェクト参照を間違えて割り当てた場合は、簡単にエラーが検出されます。
標準SQLData
インタフェースはSQLオブジェクト・マッピングのみをサポートすることに注意してください。このため、カスタム・オブジェクト・クラスを作成するとき、JPublisherに標準SQLData
インタフェースを実装するように指示すると、カスタム参照クラスは生成されません。この場合、唯一のオプションは、標準java.sql.Ref
インスタンスまたはoracle.sql.REF
インスタンスを使用して、オブジェクト参照にマップすることです。