目次 | 前の項目 | 次の項目 | JDBCTM ガイド: 入門 |
JDBC 2.0 API には、Java アプリケーションとデータベース間のデータ交換に必須のプロパティだけが含まれた、新しい SQL3 の型のモデルが取り入れられています。SQL3 ドラフトが公式の規格となる前に、新しい SQL3 の型の構文やサーバ側のセマンティクスが変更されても、JDBC 2.0 API はその影響を受けないはずです。
SQL3 ドラフトでは、以下のようなデータ型が規定されています。
REF
値は、データベースに存在する構造化型のインスタンスを永続的に示します。
LOCATOR
はクライアント環境でだけ使用され、データベースサーバ上のデータを指す一時的で論理的なポインタです。ロケータで参照するのは、一般に、イメージまたはオーディオなど、大きすぎてクライアント上で生成できないデータです。ロケータが参照するデータのランダムアクセス可能な要素を取得するための演算子が SQL レベルで定義されています。
次の項以降では、前述した新しい SQL 型にアクセスするために JDBC 2.0 API で用意されているデフォルトの機構を説明します。JDBC 2.0 API では、SQLの弁別型および構造化型の Java クラスへのマッピングをカスタマイズするための機構も用意されています。この機構については、第 9 章で説明します。
ResultSet
インタフェースと CallableStatement
インタフェースに含まれる getBlob(
) メソッドと getClob(
) メソッドにより取得できます。例を次に示します。
このコードは、結果セットの最初の列から BLOB 値を、2 番目の列から CLOB 値を取得しています。Blob blob = rs.getBlob(1); Clob clob = rs.getClob(2);
Blob
インタフェースには、BLOB の長さを返すメソッドや、BLOB に含まれる特定の範囲のバイトを返すメソッドなどが含まれています。Clob
インタフェースには、これに対応する文字ベースのメソッドが含まれています。詳細については、付属の API ドキュメントを参照してください。
JDBC アプリケーションでは、SQL で定義されている LOCATOR(blob) 型と LOCATOR(clob) 型を直接は扱いません。JDBC ドライバでは、適切なロケータ型を使用して、Blob
インタフェースと Clob
インタフェースをデフォルトで実装すべきです。また、デフォルトでは、Blob
オブジェクトと Clob
オブジェクトは、それが作成されたトランザクション内でだけ有効です。このデフォルトの寿命は、JDBC ドライバで変更できます。たとえば、セッションの存在中、有効となるように寿命を変更することができます。ただし、その変更方法については JDBC 2.0 API では規定していません。
Blob
値と Clob
値は、setBlob()
メソッドと setClob()
メソッドをそれぞれ使用することで、JDBC のほかのデータ型と同じように PreparedStatement
オブジェクトに入力パラメータとして引き渡すことができます。ストリーム値を BLOB として入力するには、setBinaryStream()
メソッドと setObject()
メソッドを使用します。また、ストリームを CLOB 値として入力するには、setAsciiStream()
、setUnicodeStream()
、setObject()
の各メソッドを使用します。
BLOB
と CLOB
の新しい 2 つの型コードが java.sql.Types
に追加されました。これらの値は、JDBC ドライバがそのデータ型をサポートしていれば、DatabaseMetaData.getTypeInfo()
や DatabaseMetaData.getColumns()
などのメソッドで取得できます。
ResultSet
インタフェースと CallableStatement
インタフェースの getArray()
メソッドを使用すれば取得できます。例を次に示します。
このコードは、結果セットの最初の列からArray a = rs.getArray(1);
Array
の値を取得しています。JDBC ドライバでは、SQL LOCATOR(array) を内部的に使用して Array
インタフェースをデフォルトで実装すべきです。また、デフォルトでは、Array
オブジェクトはそれが作成されたトランザクション内でだけ有効です。Blob
型と Clob
型について、このデフォルトの寿命を変更できます。ただし、その変更方法については JDBC 2.0 API では規定していません。
Array
インタフェースには、生成された Java 配列または ResultSet
オブジェクトとして、配列の内容をクライアントに返すメソッドが含まれています。それぞれ、getArray()
メソッドと getResultSet()
メソッドです。詳細は、別途提供されている API のドキュメントを参照してください。
Array
値を入力パラメータとして PreparedStatement に引き渡すには、PreparedStatement.setArray()
メソッドを使用します。プログラミング言語 Java の配列を入力パラメータとして引き渡すには、PreparedSatement.setObject()
を使用します。ARRAY
が java.sql.Types
に追加されました。この値は、JDBC ドライバが Array
型をサポートしていれば、DatabaseMetaData.getTypeInfo()
や DatabaseMetaData.getColumns()
などのメソッドで取得できます。
ResultSet
インタフェースと CallableStatement
インタフェースの getRef()
を使用すれば取得できます。例を次に示します。
このコードは、結果セットの最初の列からRef ref = rs.getRef(1);
Ref
値を取得しています。デフォルトでは、Ref
値を取得しても、Ref
が参照するデータは生成されません。また、デフォルトでは、Ref 値はそれが作成されたセッションまたは接続が開かれている間有効です。このデフォルトの寿命は変更できますが、その方法については JDBC 2.0 API では規定していません。
Ref
インタフェースには、逆参照のためのメソッドは含まれていません。その代わり、Ref
は、それが参照するオブジェクトを取り出す適切な SQL 文に入力パラメータとして引き渡すことができるようになっています。詳細については、別途提供されている API ドキュメントを参照してください。
Ref
を入力パラメータとして PreparedStatement に引き渡すには、PreparedStatement.setRef()
メソッドを使用します。
REF
が java.sql.Types
に追加されました。この値は、JDBC ドライバが Ref
型をサポートしていれば、DatabaseMetaData.getTypeInfo()
や DatabaseMetaData.getColumns()
などのメソッドで取得できます。
getXXX()
メソッドを使用すれば取得できます。型宣言の例を次に示します。
CREATE TYPE MONEY AS NUMERIC(10,2)
これは、ベースになっている SQL NUMERIC 型が、JDBC でjava.math.BigDecimal bd = rs.getBigDecimal(1);
java.math.BigDecimal
にマッピングされているからです。
PreparedStatement.setXXX()
メソッドを使用します。たとえば、上の MONEY 型を定義した弁別型の場合は、PreparedStatement.setBigDecimal()
を使用します。
DISTINCT
が java.sql.Types
に追加されました。この値は、JDBC ドライバがこのデータ型をサポートしている場合は、DatabaseMetaData.getTypeInfo()
や DatabaseMetaData.getColumns()
などのメソッドで取得できます。
SQL DISTINCT 型は、スキーマのテーブル定義で使用する前に、特定のデータベーススキーマの一部として定義しておかなければなりません。スキーマ固有のユーザ定義型 (DISTINCT
など) に関する情報は、DatabaseMetaData.getUDTs()
メソッドで取得できます。例を次に示します。
int[] types = {Types.DISTINCT};
ResultSet rs = dmd.getUDTs("catalog-name", "schema-name",
"%", types);
このコードでは、catalog-name.schema-name
スキーマで定義されているすべての SQL DISTINCT 型の情報が返されます。ドライバが UDT をサポートしていない場合、あるいは一致する UDT が見つからない場合は、空の結果セットが返されます。
TYPE_CAT | String => 型のカタログ (NULL も可) |
TYPE_SCHEM | String => 型のスキーマ (NULL も可) |
TYPE_NAME | String => データベースの型名 |
JAVA_CLASS | String => Java クラス名またはインタフェース名 |
DATA_TYPE | short => java.sql.Types で定義されている値 (DISTINCT など)
|
REMARKS | String => 型に関する説明 |
ほとんどの列については特に説明しません。TYPE_NAME は、上の例で DISTINCT 型に与えられた SQL の型名 (MONEY) です。これは、CREATE TABLE 文で、この型の列を指定するために使用する名前です。
DATA_TYPE が Types.DISTINCT
の場合、JAVA_CLASS 列には、完全指定 Java クラス名が含まれます。このクラスのインスタンスは、この DISTINCT 型の列に対して getObject()
を使用すると作成されます。たとえば、JAVA_CLASS は、上記の MONEY の場合はデフォルトで java.math.BigDecimal
になります。JDBC 2.0 API では、JAVA_CLASS で指定されたクラスのサブタイプをドライバが返すのを禁止していません。JAVA_CLASS の値は、その使用時、カスタム型マッピングを反映した値になります。詳細は、第 9 章を参照してください。
getObject()
メソッドにより取得できます。デフォルトでは、getObject()
は特定の構造化型に対応する Struct
型の値を返します。例を次に示します。
Struct struct = (Struct)rs.getObject(1);
このコードは、結果セット rs
の現在の行の最初の列から Struct
値を取得しています。Struct
インタフェースには、構造化型の属性を java.lang.Object
値の配列として取得するためのメソッドが含まれています。JDBC ドライバでは、Struct
への参照をアプリケーションに返す前に、Struct
の内容をデフォルトで生成する必要があります。また、デフォルトでは、Struct
オブジェクトは Java アプリケーションでその参照が保持されている間有効です。このデフォルトの寿命は、JDBC ドライバで変更できます (SQL LOCATOR が使用できるようにするなど)。ただし、その方法については JDBC 2.0 API では規定していません。
Struct
を入力パラメータとして PreparedStatement に引き渡すには、PreparedStatement.setObject()
メソッドを使用します。
STRUCT
が java.sql.Types
に追加されました。この値は、JDBC ドライバが構造化データ型をサポートしている場合、DatabaseMetaData.getTypeInfo()
や DatabaseMetaData.getColumns()
などのメソッドで取得できます。
SQL の構造化型は、スキーマのテーブル定義で使用する前に、特定のデータベーススキーマの一部として定義しておかなければなりません。スキーマ固有のユーザ定義型 (STRUCT
など) に関する情報は、DatabaseMetaData.getUDTs()
メソッドで取得できます。例を次に示します。
int[] types = {Types.STRUCT};
ResultSet rs = dmd.getUDTs("catalog-name", "schema-name",
"%", types);
このコードでは、catalog-name.schema-name
スキーマで定義されているすべての SQL 構造化型の情報が返されます。ドライバが UDT をサポートしていない場合や、一致する UDT が見つからない場合は、空の結果セットが返されます。getUDTs()
によって返される結果セットについては、8.5.3 項を参照してください。
getUDTs()
で返される DATA_TYPE が Types.STRUCT
の場合、JAVA_CLASS 列には、Java クラスの完全指定 Java クラス名が含まれます。このクラスのインスタンスは、この STRUCT 型の列に対して getObject()
を使用すると、JDBC ドライバにより作成されます。したがって、JAVA_CLASS は、構造化型の場合はデフォルトで java.sql.Struct
になります。このデフォルトの動作を Java アプリケーションで変更する方法については、第 9 章で説明しています。なお、JDBC 2.0 API では、JAVA_CLASS で指定されたクラスのサブタイプをドライバが返すのを禁止していません。