注: この章の内容の一部は、Addison Wesley 社より Java シリーズの 1 巻として出版された『JDBCTM API Tutorial and Reference, Second Edition: Universal Data Access for the JavaTM 2 Platform』(ISBN 0-201-43328-1) に基づいて作成したものです。
この付録では、JDBC API にこれまで追加されてきた新機能を要約しています。ただし、特定の機能を使用するには、その機能をサポートしているドライバを使用する必要があります。
JDBC 3.0 API の主な変更点の 1 つは、パッケージ java.sql
だけでなくパッケージ javax.sql
(JDBC オプションパッケージ) も、API に含まれるようになったことです。この概要説明は前半と後半に分かれています。前半のセクションでは、JDBC 3.0 API で両方のパッケージに追加された機能について説明します。後半のセクションでは、JDBC 2.0 オプションパッケージに追加された機能について説明します。詳細については、JDBC 3.0 API 仕様を参照してください。
JDBC 3.0 API に追加された新しい資料や変更点は、次のとおりです。
Savepoint
インタフェースが追加されました。このインタフェースに含まれる新しいメソッドを使えば、セーブポイントの設定、セーブポイントを解放、および指定されたセーブポイントへのトランザクションのロールバックを行えます。
準備された文が接続によってどのようにプールおよび再利用されるかを、開発者が制御できるようにするための機能が追加されました。
ConnectionPoolDataSource
インタフェース用のプロパティが、数多く定義されました。これらのプロパティを使えば、DataSource
オブジェクトによって作成されるPooledConnection
オブジェクトが、どのようにプールされるかを記述できます。
新しいインタフェース ParameterMetaData
が追加されました。このインタフェースは、準備された文に対するパラメータの、個数、型、およびプロパティを記述します。
自動生成値が格納されている列から値を取得するための方法が追加されました。
ResultSet
オブジェクトを複数作成する機能
新しいメソッドgetMoreResults(int)
が追加されました。このメソッドには、Statement
から返されたResultSet
オブジェクトを閉じたあとで後続のResultSet
オブジェクトを返すかどうかを示す引数を指定します。
CallableStatement
オブジェクトへの名前によるパラメータの受け渡し
CallableStatement
オブジェクトのパラメータを識別する文字列を設定するメソッドが追加されました。
トランザクションのコミット後に ResultSet
オブジェクトを開いたままにするかどうかを指定する機能が追加されました。
BOOLEAN
データ型
データ型java.sql.Types.BOOLEAN
が追加されました。BOOLEAN
は、論理的にはBIT
と同等です。
Blob
オブジェクトおよび Clob
オブジェクト内のデータに対する内部的な更新
Blob
オブジェクトおよびClob
オブジェクトに格納されたデータを変更するためのメソッドが追加されました。
Ref
オブジェクトによって参照されているオブジェクトの取得および更新
Ref
オブジェクトによって参照されているオブジェクトを取得するためのメソッドが追加されました。また、Ref
オブジェクトによって参照されているオブジェクトを更新するための機能も追加されました。
BLOB
、CLOB
、ARRAY
、REF
の型を含む列の更新
updateBlob
、updateClob
、updateArray
、updateRef
の各メソッドがResultSet
インタフェースに追加されました。
DATALINK/URL
データ型
データ型 java.sql.Types.DATALINK
が追加されました。JDBC ドライバはこのデータ型を使うことで、外部データへの参照を格納および取得できるようになります。
変換グループの効果とそれがどのようにメタデータに反映されるかについて、記述しました。
JDBC SPI とコネクタアーキテクチャの関係について、記述しました。
DatabaseMetadata
API
SQL 型の階層構造やその他の新機能に関する各種情報を取得するためのメタデータが追加されました。
次の機能は、javax.sql
パッケージに追加されましたが、今回、JDBC 3.0 API の一部となり、また、J2SE バージョン 1.4 にも追加されました。
DataSource
オブジェクトによる接続の取得
JNDI API と新しい DataSource
インタフェースを使用すれば、アプリケーションからデータソースに接続する際に、ドライバ名をコード内で指定する必要がなくなります。JNDI ネーミングサービスに登録された論理名を指定すれば、DataSource
オブジェクトを取得できます。このオブジェクトを使えば、目的のデータソースへの接続を取得できます。この機能により、コードの移植性が高まり、コードの保守も非常に楽になります。
接続プールを使えば、アプリケーションは、すでに確立されたデータベース接続を再利用できるようになるため、常に新しい接続を作成する必要がなくなります。データベース接続の作成と廃棄は非常に負担のかかる処理であるため、良好なパフォーマンスを達成するうえで接続プールは重要です。サーバアプリケーションの場合は特にそうです。
JDBC 2.0 オプションパッケージ API には、JDBC ドライバ層の上部に接続プールを実装することを可能にするフックが含まれています。これにより、使用中のすべての JDBC ドライバに対する単一の接続キャッシュを提供することが可能になります。
JDBC 2.0 オプションパッケージ API を使えば、JDBC ドライバは、Java Transaction API (JTA) に定義されている標準 2 段階コミットプロトコルをサポートできます。このことは、1 つのトランザクションを複数のサーバに分散できることを意味します。したがって、開発者は、Enterprise JavaBeansTM コンポーネントを使って、複数の DBMS サーバにまたがってトランザクション処理を行うようなエンタープライズアプリケーションを記述することができます。
RowSet
オブジェクトは、表形式データを格納するためのコンテナにほかなりません。このオブジェクトは、JDBC API の上層部に実装されます。行セットを使えば、ネットワーク経由で行データをやり取りできます。このため、行セットは分散アプリケーションで頻繁に使用されることになります。行セットは、データソースへの接続を切断することで大幅に軽量化できます。したがって、行セットを使えば、thin クライアント上にデータを表示することが可能になります。また、行セットを使えば、基となる DBMS がスクロール可能な結果セットをサポートしていない場合でも、スクロールを使用できます。行セットは、JavaBeansTM コンポーネントであるため、アプリケーション構築時の取り扱いも簡単です。開発ツールを使う場合は特にそうです。
通常の場合、RowSet
の実装はサードパーティが提供してくれるため、アプリケーションプログラマは、提供された実装をただ使うだけです。RowSet
実装の API は一般に、使い方が非常に簡単です。というのも、行セットの機能の大部分は、ResultSet
インタフェースから継承されたものであるからです。行セットの複雑な側面はすべて内部的に処理されるため、そうした部分がアプリケーションプログラマの目に触れることはありません。現時点で、RowSet
インタフェースの Early Access 版実装が 3 つ存在しています。これらの実装は、Java Developer Connection (http://developer.java.sun.com/developer
) から入手できます。
JDBC 2.0 コア API は、JDBC 1.0 API を含み、さらに拡張機能および新しい機能を追加しています。これらの追加された機能により、汎用的なデータアクセスと向上したパフォーマンスの提供によって、データベースコンピューティングの最前線に Java プログラミング言語を位置付けます。
「下位互換性の目標」に従っているので、旧バージョンの JDBC API を使用するアプリケーションは、Java 2 プラットフォームを使って問題なく実行できます。しかし、2.0 の新しい特徴を利用するアプリケーションは、それらの特徴を実装しているドライバとともに実行しなければなりません。
JDBC 2.0 コア API の新しい特徴は、新しい機能のサポートと SQL99 データ型のサポートの 2 つに大きく分類されます。
データの検索、保存、操作が便利になり、さらに、新しい特徴により JDBC アプリケーションの効率がより良くなります。たとえば、バッチ更新により性能が大幅に向上します。新しい Blob
、Clob
、Array
インタフェースにより、アプリケーションはクライアント上にデータを実体化することなく、大量のデータを操作することができるので、転送時間と必要なメモリ容量の大きな節約につながります。また、フェッチサイズとフェッチ方向の設定のための新しいメソッドにより、プログラマはアプリケーションを微調整して、より効率的なデータ検索と処理を達成できます。
JDBC 2.0 コア API は、重要な新機能を追加しています。ここでは、それぞれの新しい機能範囲について簡単に説明し、サポートしている API をまとめます。
スクロール可能な結果セットは、現在のカーソル位置からの相対位置または指定の位置に、カーソルを進めたり戻したりできます。次のインタフェースには、スクロール可能な結果セットをサポートする新しいメソッドがあります。
新しいバッチ更新機能により、更新を個別に送信せずに、データベースに複数の更新を一度に送信してバッチ実行することができます。次のインタフェースには、バッチ更新をサポートするメソッドが追加されています。 BatchUpdateException
例外は新規です。
プログラム的な更新により、SQL 文ではなく JDBC API を使って更新を行うことができます。次のインタフェースには、プログラム的な更新をサポートする新しいメソッドと定数があります。
updater
メソッド
JDBC 2.0 コア API には、上記の他に、さまざまな新しい特徴があります。 この特徴を以下にまとめます。
ResultSet
メソッド
Statement
、PreparedStatement
、および CallableStatement
メソッド。 このデフォルトの設定は、クエリーの実行により結果セットが最初に作成されるときにその結果セットに設定されます。
getUnicodeStream
と setUnicodeStream
の 2 つのメソッドを置き換えています。
ResultSet.getCharacterStream
CallableStatement.getCharacterStream
PreparedStatement.setCharacterStream
java.math.BigDecimal
値の完全な精度 - java.math.BigDecimal
値を完全な精度で扱う、新しいバージョンのメソッド。推奨されていないバージョンとは異なり、新しいバージョンでは精度の指定を受け取りません。
Calendar
オブジェクトを受け取る新しいバージョンのメソッド。 ドライバにおいて、日付、時間、タイムスタンプの値を計算するとき、デフォルトではなく指定されたタイムゾーンを使用できます。
JDBC 2.0 コア API には高度なデータ型のサポートが追加されており、高度なデータ型を単純なデータ型と同じくらい簡単に使用できます。このサポートには、本質的にはオブジェクトである新しい SQL データ型の保存、検索、更新の機能も含まれるので、オブジェクトデータベースとリレーショナルデータベースの明確な区別をなくすことができます。以下の 4 つの節 ([A.4.1 SQL99 データ型とは何か」、「A.4.2 SQL99 データ型のサポートの概要」、「A.4.3 SQL99 型のマッピング」、「A.4.4 SQL ロケータ」) で、JDBC 2.0 コア API の高度なデータ型のサポートについて説明します。
SQL で定義されているオブジェクトをデータベーステーブル内の値として保存できるだけではなく、Java アプリケーションを作成するプログラマは、Java プログラミング言語で定義されているオブジェクトをデータベーステーブル内の値として保存することができます。「A.4.5 Java オブジェクト保存のサポート」で、この機能について説明します。
ドライバは、そのドライバの DBMS がサポートしていない機能を実装するようには、要求されていません。 そのため、すべてのドライバが、ここで説明している機能を実装する必要はありません。getTypeInfo
、getColumns
、getUDTs
などの DatabaseMetaData
メソッドを呼び出して、ドライバがサポートしているデータ型の情報を取得することができます。
ここでは新しい SQL99 データ型について説明します。Java プログラミング言語のデータ型へのこれらのデータ型のマッピングについては、「A.4.3 SQL99 型のマッピング」で説明します。
CHAR
、FLOAT
、DATE
などの標準の組み込みデータ型に追加されます。
CREATE TYPE
により作成される新しいデータ型
JDBC 2.0 コア API は、次の新しいインタフェース、メソッド、フィールドによって、新しい SQL99 データ型をサポートします。
ResultSet
インタフェースの新しい getter
メソッド。結果セットから SQL99 型の列値を取得する
CallableStatement
インタフェースの新しい getter
メソッド。出力パラメータ内の SQL99 型の値を取得する
PreparedStatement
インタフェースの新しい setter
メソッド。SQL99 型の列値を設定する
ResultSet
インタフェースの新しい updater
メソッド。プログラムにより値を更新する
DatabaseMetaData
と ResultSetMetaData
インタフェースのメソッド。 SQL99 データ型に関するメタデータを取得する
java.sql.Types
クラスに追加されたフィールド (定数)。 新しいデータ型と永続的な保存をサポートする
JDBC API では、SQL99 データ型の正確な複製を試みるのではなく、それらのデータ型を Java プログラミング言語の型にマッピングすることにより、それらのデータ型の機能性を維持し、使用の便宜をはかることを目標とします。たとえば、SQL99 には「ロケータ型」と呼ばれるデータ型があり、データベースサーバに保存されているデータを指すためにクライアント上で使用されます。ロケータではクライアントマシン上にデータを実体化しなくてもデータを操作できるので、大きなデータを扱う場合に役立ちます。SQL99 には、ARRAY
、BLOB
、CLOB
型と構造化型のためのロケータが含まれています。JDBC API には、直接的にはこれらのデータ型のためのロケータは含まれていません (構造化型のためのロケータはまったくありません) が、ドライバと DBMS が状況に合わせて適切なロケータを使用するように実装されたインタフェースがあります。その結果、JDBC API を使って SQL の ARRAY
、BLOB
、CLOB
型の値にアクセスする場合、開発者はロケータについて考える必要はありません。
SQL99 型から Java プログラミング言語のインタフェースへのマッピングは、次のとおりです。
ARRAY
- java.sql.Array
へマッピングされる
BLOB
- java.sql.Blob
へマッピングされる
CLOB
- java.sql.Clob
へマッピングされる
REF
- java.sql.Ref
へマッピングされる
java.sql.Struct
へマッピングされる
個別型は単一の組み込み型を基にしているため、単純にその組み込み型への標準的なマッピングにマッピングされ、インタフェースにはマッピングされません。たとえば、次の SQL 文は新しいデータ型 MONEY
を作成します。
CREATE TYPE MONEY AS NUMERIC(10, 2)
この新しい UDT は java.math.BigDecimal
にマッピングされるデータ型 NUMERIC
を基にしています。そのため、データ型 MONEY
は java.math.BigDecimal
にマッピングされます。したがって、MONEY
型の値は getBigDecimal
メソッドで取得され、setBigDecimal
メソッドで保存され、updateBigDecimal
メソッドで更新されます。
SQL LOCATOR
は、データベースサーバ上のデータへの論理ポインタです。一般に、画像やオーディオなど、クライアント上に生成するには大きすぎるデータを参照します。ロケータはクライアント環境にのみ存在し、その存在は一時的です。標準実装では、インタフェース Blob
、Clob
、Array
のインスタンスに対して、ロケータを内部的に使用します。つまり、Blob
、Clob
、Array
オブジェクトにはデータそのものが含まれているのではなく、サーバ上のデータを指すロケータが含まれています。Blob
、Clob
、Array
インスタンスを操作するということは、実際には、それらが表すデータベースオブジェクトを操作していることになります。クライアントにデータを持ち込まずに大きなデータベースオブジェクトを操作するこの機能は、性能に大きく貢献します。
ただし、SQL LOCATOR(
構造化型)
の使用を、JDBC API が必要としているわけではありません。標準的な実装では、Struct
オブジェクトには、それがマッピングされる構造化型のデータが含まれていて、Blob
、Clob
、Array
オブジェクトのような内部的なロケータとしては実装されていません。
JDBC API では、Java プログラミング言語に定義されているオブジェクトの永続的な保存を、getObject
、setObject
メソッドを通じて、常にサポートしてきました。もちろん、Java オブジェクトの永続的な保存は、DBMS がそれをサポートしていない限り実際には起り得ません。このためサポートには制限がありますが、Java オブジェクトをデータ型として認識する新世代の DBMS が出現しつつあります。Java リレーショナル DBMS と呼ばれるこれらの DBMS では、Java クラスのインスタンスをデータベーステーブル内の列の値として保存できます。