[目次] [前の項目] [次の項目]

Connection

注: この章の内容は、Addison Wesley 社より Java シリーズの 1 巻として出版された『JDBCTM API Tutorial and Reference, Second Edition: Universal Data Access for the JavaTM 2 Platform』(ISBN 0-201-43328-1) に基づいています。

2.1 Connection の概要

Connection オブジェクトは、データベースとの接続を表します。 接続セッションには、実行される SQL 文とその接続を介して返された結果が入ります。 1 つのアプリケーションが 1 つのデータベースとの 1 つ以上の接続を持つことも、多くの異なるデータベースとの接続を持つこともできます。

Connection.getMetaData メソッドを呼び出すと、Connection オブジェクトのデータベースの情報を取得できます。このメソッドは、データベースのテーブル、サポートしている SQL 文法、ストアドプロシージャ、この接続の機能などの情報が含まれている DatabaseMetaData オブジェクトを返します。

2.1.1 接続の開始

データベースとの接続を確立する従来の方法は、メソッド DriverManager.getConnection を呼び出すことです。 このメソッドは、URL の入った文字列をパラメータとして受け取ります。 JDBC 管理レイヤと呼ばれる DriverManager クラスは、URL が表すデータベースに接続できるドライバの検索を試みます。 DriverManager クラスは登録済みの Driver クラスのリストを持ち、メソッド getConnection が呼び出されると、URL で指定されたデータベースに接続できるドライバが見つかるまで、リストの中の各ドライバを確認します。 Driver のメソッドの connect は、この URL を使用して実際に接続を確立します。

ユーザは、JDBC 管理レイヤをバイパスして、Driver メソッドを直接呼び出すことができます。 これは、2 つのドライバがデータベースに接続でき、ユーザが特定のドライバを明示的に選択するというまれなケースでは役に立ちます。 しかし、通常は、DriverManager クラスに接続の開始を処理させる方がはるかに簡単です。

以下のコードは、oboy という ID と 12Java というパスワードを使用して URL jdbc:odbc:wombat にあるデータベースへの接続を開始する例を示します。

			String url = "jdbc:odbc:wombat";
Connection con = DriverManager.getConnection(url, "oboy", "12Java");

JDBC 2.0 標準拡張機能 API では、接続を確立するために、DriverManager の代替として DataSource インタフェースが提供されています。 DataSource クラスが適切に実装されている場合は、DataSource オブジェクトを使用して、接続プールに関係する Connection オブジェクトまたは分散トランザクションに関係する Connection オブジェクト、あるいはその両方を作成できます。 詳細および DataSource オブジェクトを使用して接続を作成するコード例については、「DataSource」の章を参照してください。この章では、接続を作成するのに、DataSource オブジェクトの使用が良い代替方法になる理由についても説明します。

アプリケーションでは、DataSource オブジェクトによって生成された Connection オブジェクトは、基本的に DriverManager によって生成された Connection オブジェクトと同じ方法で使用されます。 ただし、いくつか相違点があります。 Connection オブジェクトがプールされた接続の場合は、アプリケーションに finally ブロックを組み込み、例外がスローされたときにも接続が閉じるようにする必要があります。 この結果、接続が有効な場合は、常に有効な接続プールに戻ります。

Connection オブジェクトが分散トランザクションの一部である場合は、アプリケーションから Connection.commit メソッドまたは Connection.rollback メソッドを呼び出したり、接続の自動コミットモードをオンに設定したりしないでください。 トランザクションマネージャの分散トランザクション処理を妨害する可能性があります。

2.1.2 URL の一般的な使用法

アプリケーションから DriverManager を使用して Connection オブジェクトを生成するときは、URL を DriverManager.getConnection メソッドに渡す必要があります。URL に関しては混乱が生じることがよくあるので、まず URL の一般的な説明を手短かに行なってから、JDBC の URL について説明することにします。

URL (Uniform Resource Locator) は、インターネット上のリソースの位置を指定するために使用します。 これはアドレスと考えることができます。

URL の最初の部分で、情報にアクセスするために使用するプロトコルを指定します。 そのあとには常に、コロンが続きます。 よく使用されるプロトコルには、ファイル転送プロトコルを指定する ftp とハイパーテキスト転送プロトコルを指定する http があります。 プロトコルが file の場合は、リソースはインターネット上ではなくローカルファイルシステムに格納されていることを示します。

      ftp://javasoft.com/docs/JDK-1_apidocs.zip
      http://java.sun.com/products/JDK/CurrentRelease
      file:/home/haroldw/docs/tutorial.html

URL の最初のコロンのあとに続く残りの部分はすべて、データソースがどこにあるかを指定するものです。 プロトコルが file の場合には、URL の残りの部分はファイルに対するパスになります。 プロトコルが ftphttp の場合には、URL の残りの部分はホストを指定するもので、より具体的なサイトに対するパスをオプションとして指定することもできます。 たとえば、次は、Java ソフトウェアのホームページに対する URL となります。 この URL はホストだけを指定します。

http://www.java.sun.com

このホームページから、多数のほかのホームページに行くことができます。 JDBC ホームページもその 1 つです。 JDBC ホームページの URL はより具体的で、次のようになっています。

http://www.java.sun.com/products/jdbc

2.1.3 JDBC の URL

JDBC の URL は、適切なドライバがデータソースを認識してそれとの接続を確立するように、データソースを識別する方法を提供します。 ドライバの作成者が、特定のドライバを識別する JDBC URL を何にするかを実際に決定します。 ユーザは、JDBC URL をどのような形式するかについては心配する必要はありません。 ユーザは、その使用しているドライバが供給する URL を単に使用するだけですみます。 JDBC の役割は、単にドライバの作成者が JDBC の URL を構成する際に使用する規則を推奨するだけです。

JDBC の URL は、さまざまな種類のドライバで使用するため、規則は当然、非常に柔軟です。 まず、この規則では、異なるドライバがデータベースを名付けるための異なる仕組みを使用できます。 たとえば、odbc サブプロトコルを使用すると、URL に属性値を含めることができます (ただし、必要とするわけではない)。

第 2 に、JDBC の URL により、ドライバの作成者が必要な接続情報をその中に符号化できるようになります。 これにより、たとえば、アプレットがデータベースとやり取りを行おうとする際、ユーザがなんらの管理作業を行うことなくデータベース接続を開始することができます。

第 3 に、JDBC の URL では間接的なレベルが可能です。 すなわち、JDBC の URL が、論理ホスト、またはネットワークネーミングシステムによって実際の名前に動的に翻訳されるデータベース名を参照できるということです。 これにより、システム管理者は特定のホストを JDBC 名の一部として指定しなくてすみます。 ネットワークネームサービスにはいくつかの異なる種類 (たとえば、DNS、NIS、および DCE) があり、どれを使用するかについての制約はありません。

JDBC URL の標準構文は以下のとおりです。 その構文には 3 つの部分があり、コロンによって区切られています。

	jdbc:<subprotocol>:<subname>

JDBC の URL の 3 つの部分は以下のように分割できます。

  1. jdbc はプロトコルです。 JDBC のURL のプロトコルは常に jdbc です。
  2. <subprotocol> は通常、ドライバ名またはデータベース接続機構の名前で、1 つ以上のドライバによってサポートすることができます。 サブプロトコル名の顕著な例は、odbc で、これは OBDC スタイルデータソース名を指定する URL のために予約されています。 たとえば、JDBC-ODBC ブリッジによってデータベースにアクセスするには、以下のように URL を使用します。
    	jdbc:odbc:fred
    

    この例では、サブプロトコルは odbc で、サブネームはローカルの ODBC データソース名 fred です。

    ネットワークネームサービスを使用したい (JDBC の URL 中のデータベース名を実際の名前にする必要をなくしたい) 場合には、ネームサービスはサブプロトコルにすることができます。 すなわち、たとえば、次のような URL を持っているものとします。

    	jdbc:dcenaming:accounts-payable
    
    この URL は、「ローカルの DCE ネームサービスを使ってデータベース名 accounts-payable を解釈して、実際のデータベースへの接続に使用できる特定の名前に変換する」ことを指定しています。
  3. <subname> は、データソースを識別する方法です。 サブネームは、サブプロトコルによってさまざまに変化することができ、ドライバの作成者が選択する、サブサブネームを含むどのような内部構文でも持つことができます。 サブネームのポイントは、データソースを探すために十分な情報を提供することです。 上記の例では、ODBC が残りの情報を提供するので、fred で十分です。 しかし、リモートサーバ上のデータソースでは、もっと多くの情報が要求されます。 たとえば、データソースがインターネット経由でアクセスされる場合は、ネットワークアドレスがサブネームの一部として JDBC の URL に含まれるべきであり、次の標準の URL 命名規則に従う必要があります。
     	//hostname:port/subsubname 
    

    dbnet がインターネット上のホストに接続するためのプロトコルだとすると、JDBC の URL は以下のような形になります。

    	jdbc:dbnet://wombat:356/fred
    

2.1.4 "odbc" のサブプロトコル

サブプロトコル odbc は、特別なケースです。 これは ODBC スタイルのデータソース名を指定する URL のために予約され、サブネーム (データソース名) のあとに任意の数の属性値を指定できるようにする特別な機能を備えています。 odbc サブプロトコルの完全な構文は以下のとおりです。

  jdbc:odbc:<data-source-name>[;<attribute-name>=<attribute-value>]*

したがって、以下はすべて有効な jdbc:odbc 名です。

     jdbc:odbc:qeor7
     jdbc:odbc:wombat
     jdbc:odbc:wombat;CacheSize=20;ExtensionCase=LOWER
     jdbc:odbc:qeora;UID=kgh;PWD=fooey

2.1.5 サブプロトコルの登録

ドライバ開発者は、JDBC の URL でサブプロトコルとして使用する名前を予約することができます。 DriverManager クラスがこの名前をその登録済みドライバのリストに示すと、この名前で予約されたドライバがそれを認識して、それによって識別されるデータベースへの接続を確立します。 たとえば、「odbc」は JDBC-ODBC ブリッジのために予約されています。 また、仮に Miracle Corporation という企業が存在すれば、その Miracle DBMS に接続する JDBC ドライバのサブプロトコルとして「miracle」を登録して、ほかに誰もその名前を使えないようにします。

Java ソフトウェアは JDBC サブプロトコル名の非公式な登録機関として活動しています。 サブプロトコル名を登録するには、以下のアドレスに電子メールを送ります。

	jdbc@eng.sun.com

2.1.6 SQL 文の送付

いったん確立されると、接続は、SQL 文をその基盤となるデータベースに渡すために使用されます。 JDBC API は送付される SQL 文の種類について何の制約も課していないので、大きな柔軟性があり、データベース固有の文や SQL でない文でさえも使用することができます。 ただしユーザは、基盤となるデータベースが送付される SQL 文を処理できることを確認する責任があり、処理できない場合はその結果を甘受する必要があります。 たとえば、アプリケーションが、ストアドプロシージャをサポートしない DBMS にストアドプロシージャ呼び出しを送信しようとすると、正常には処理されず、例外処理を生成します。

JDBC API は、SQL 文をデータベースに送付するために、以下の 3 つのインタフェースを用意しており、Connection インタフェースの対応するメソッドはそのインスタンスを生成します。 SQL 文およびそれを作成する Connection メソッドを送信するインタフェースは、次のとおりです。

  1. Statement - Connection.createStatement メソッドによって生成されます。Statement オブジェクトは、パラメータを指定しないで SQL 文を送信するときに使用します。
  2. PreparedStatement - Connection.prepareStatement メソッドによって生成されます。PreparedStatement オブジェクトは、プリコンパイルされた SQL 文に使用します。SQL 文には、1 つ以上のパラメータを入力引数 (IN パラメータ) として指定できます。 PreparedStatement は IN パラメータの値を設定するメソッドのグループを持ち、これらの IN パラメータは文が実行されるときにデータベースに送付されます。 PreparedStatement のインスタンスは、Statement を継承しているため Statement メソッドを含みます。 PreparedStatement オブジェクトはコンパイル済みで、将来の使用に備えて格納されているので、Statement オブジェクトよりも効率的に使用できる能力を潜在的に備えています。 このため、PreparedStatement オブジェクトは、パフォーマンスの向上が必要なときに、頻繁に実行される SQL 文に対して使用します。
  3. CallableStatement - Connection.prepareCall メソッドによって生成されます。CallableStatement オブジェクトは、SQL ストアドプロシージャ (一連の SQL 文で、関数を起動するのとまったく同様に、名前によって呼び出される) を実行するために使用します。 CallableStatement オブジェクトは、IN パラメータを処理するためのメソッドを PreparedStatement から継承し、さらに、OUT および INOUT パラメータを処理するためのメソッドが追加されています。

    以下のリストは、異なるタイプの SQL 文を作成するために、どちらの Connection メソッドが適切かを素早く判定する方法を示します。

これらのメソッドでは、引数を指定しないため、デフォルトの ResultSet オブジェクトを生成する文が作成されます。すなわち、スクロールおよび更新を行うことができない結果セットが生成されます。 JDBC 2.0 API を使用すると、スクロールまたは更新、あるいはその両方を行うことができる結果セットが生成される文を作成できます。 作成するには、新しい createStatementprepareStatement、および prepareCall メソッドを使用します。これらのメソッドには、結果セットの型および作成中の結果セットの並行処理のレベルを指定するために、追加のパラメータを指定できます。 ResultSet オブジェクトの型および型を指定するための定数については、第 5 章「ResultSet」の 「結果セットの型」を参照してください。並行処理のレベルについては、「並行処理のタイプ」 を参照してください。 文を作成するときに新しい Connection メソッドを使用して ResultSet オブジェクトを生成する方法については、「タイプの異なる結果セットの作成」 を参照してください。

2.1.7 トランザクション

トランザクションは、実行され、完了され、その後にコミットもしくはロールバックする 1 つ以上の文で構成されます。 メソッド commit または rollback が呼び出された時点で、現在のトランザクションが終了し、別のトランザクションが開始します。

通常デフォルトでは、新しい Connection オブジェクトは自動コミットモードになっています。 つまり、文が完了すると、メソッド commit が自動的にその文で呼び出されます。 この場合、各文が個々にコミットされるので、1 つのトランザクションがただ 1 つの文によって構成されています。 自動コミットモードが無効になっていると、トランザクションはメソッド commit または rollback が明示的に呼び出されるまで終了しないので、1 つのトランザクションは commit または rollback メソッドの最後の呼び出し以降に実行されたすべての文を含みます。 この 2 番目の場合、トランザクションのすべての文はグループとしてコミットまたはロールバックされます。

トランザクションを開始するときに、明示的な呼び出しは必要ありません。自動コミットモードを無効にしたとき、または commit または rollback メソッドを呼び出した後に、暗黙に開始されます。 メソッド commit は、SQL 文がデータベースに対して加えたあらゆる変更を永続化し、トランザクションによってかけられたロックをすべて解放します。 メソッド rollback はそれらの変更を破棄します。

ほかの変更が同様に行われない限り、ある変更を有効にしたくない場合があります。 自動コミットを無効にし、両方の更新作業を 1 つのトランザクションにグループ化することによって実現できます。 両方の更新作業が正常に行われた場合に、commit メソッドを呼び出し、両方の更新結果をデータベースに反映します。 1 つまたは両方が失敗した場合には、rollback メソッドを呼び出し、更新作業が実行される前の値に戻します。

ほとんどの JDBC ドライバはトランザクションという概念をサポートします。 JDBC 準拠として指定されるためには、JDBC ドライバがトランザクションをサポートする必要があります。

JDBC 2.0 標準拡張機能 API では、Connection オブジェクトを分散トランザクションの一部とすることができます。つまり 1 つのトランザクションが複数の DBMS サーバとかかわり合うことができます。 Connection オブジェクトが分散トランザクションの一部である場合は、トランザクションマネージャが commit または rollback メソッドを呼び出すタイミングを決定します。 Connection オブジェクトが分散トランザクションに関係している場合には、このため、アプリケーションから接続の開始または終了のタイミングに影響する処理を行わないでください。

Connection オブジェクトを分散トランザクションに関係させるには、中間層のサーバの分散トランザクションインフラストラクチャと共に動作するように実装された、DataSource オブジェクトを使用して Connection オブジェクトを生成する必要があります。 DriverManager によって生成された Connection オブジェクトと異なり、DetaSource オブジェクトのようなオブジェクトによって生成された Connection オブジェクトは、自動コミットモードがデフォルトで無効になります。 一方、DataSource オブジェクトの標準的な実装で生成される Connection オブジェクトは、DriverManager クラスによって生成される Connection オブジェクトと完全に同じになります。

2.1.8 トランザクションの遮断レベル

DBMS がトランザクション処理をサポートする場合、DBMS には、2 つのトランザクションが 1 つのデータベース上で同時に稼動しているときに生じ得る、潜在的な競合を管理する方法がいくつかあります。 ユーザは、潜在的な競合を解決するのに、DBMS がどの程度の注意を払う必要があるかを示すトランザクションの遮断レベルを指定することができます。 たとえば、あるトランザクションが値を変更し、変更がコミットまたはロールバックされる前に、2 番目のトランザクションがその値を読み取るとどうなるでしょうか。 最初のトランザクションがロールバックした場合、2 番目のトランザクションが読み取った、変更された値が無効だということが許容されるのでしょうか。 JDBC ユーザは、以下のコードを使用して (con は現在の接続)、コミットされる前に値を読めるように (汚れた値の読み取り) 指示することができます。

con.setTransactionIsolation(TRANSACTION_READ_UNCOMMITTED);

トランザクションの遮断レベルが高くなればなるほど、競合を避けるための注意がより多く払われます。 Connection インタフェースは、トランザクションがまったくサポートされない最低レベルから、1 つのトランザクションがデータベース上で操作している間に、そのトランザクションが読み取っているデータに対して、ほかのトランザクションが変更を行わないという最高レベルまで、5 段階のレベルを定義します。 上記の例で使用された TRANSACTION_READ_UNCOMMITTED のレベルは、最低レベルの 1 つ上です。 通常、遮断のレベルが高くなると、アプリケーションを実行する速度は低下します (ロッキングによるオーバーヘッドが増大し、ユーザ間の同時使用が低減するため)。 どの遮断レベルを使用するかを決定するときは、開発者はパフォーマンス上のニーズとデータの一貫性について、ニーズのバランスを取る必要があります。 もちろん、実際にサポートされるレベルは、基盤の DBMS の能力に依存します。

Connection オブジェクトが新たに生成されると、そのトランザクションの遮断レベルは、ドライバによりますが、通常の場合には基盤のデータソースのデフォルト値になります。 ユーザはメソッド setIsolationLevel を呼び出して、トランザクションの遮断レベルを変更し、その接続セッションの残りに対しては新しいレベルを有効にできます。 1 つのトランザクションについてだけトランザクションの遮断レベルを変更するには、そのトランザクション内の文を実行する前に遮断レベルを設定する必要があります。そして、トランザクションが終了したあとにそれをリセットします。 トランザクションの最中のトランザクションの遮断レベル変更はお勧めできません。commit メソッドへの即時呼び出しのきっかけとなり、その時点までに行われたすべての変更がデータベースに反映されてしまいます。

2.1.9 DBMS リソースの解放

作成した接続および文が必要なくなった時点で、明示的にクローズすることをお勧めします。

Java プログラミング言語でコードを記述し、外部リソースを使用していない場合は、メモリ管理について心配する必要はありません。 もはや使われないオブジェクトは、ガベージコレクタによって自動的に削除され、使用していたメモリは解放されます。 メモリが不足してくると、破棄されたオブジェクトが現在閉めているメモリをすばやい再利用として使えるようにしてリサイクルします。

ただし、アプリケーションによって外部リソースが使用されている場合、つまり JDBC API を使用して DBMS にアクセスしている場合は、ガベージコレクタではそれらのリソースの状態を認識することはできません。 破棄されたオブジェクトのリサイクルは依然として行われますが、Java ヒープに空きメモリが多く存在しているときは、少量の Java のガベージが大量の高価なデータベースリソースをオープンしたままにしているにもかかわらず、ガベージコレクトがたまにしか行われません。 したがって、必要がなくなったらできるだけ早く明示的にすべての接続を Connection.close でクローズし、すべての文を Statement.close でクローズし、それによってできるだけ早く DBMS のリソースを解放することをお勧めします。 ある DBMS と他のそれとでは違いがあるので、このことは、異なる複数の DBMS を使う予定のアプリケーションに特に当てはまります。

Connection.isClosed メソッドは、Connection.close が呼び出されたあとに呼び出されたときだけ、true を返すということが保証されています。 このため、接続が有効かどうかを調べるのには、このメソッドは当てになりません。 代わりに、典型的な JDBC クライアントでは、JDBC の操作を試みたときにスローされる例外をキャッチすることで、接続が無効になっていることを判断できます。

2.1.10 型マップの使用法

SQL の構造化型および DISTINCT 型は、SQL3 の新しいデータ型です。これらは、ユーザ定義の型 (UDT) であり、Java プログラミング言語のクラスにカスタムマッピングできます。 SQL3 のすべてのデータ型と同様に、標準的なマッピングを持っていますが、カスタムマッピングも作成できます。 個々の UDT にカスタムマッピングが存在するかどうかは、java.util.Map オブジェクト内で宣言されています。この Map オブジェクトは、接続に関連付けられるか、メソッドに渡されます。

Map オブジェクトにエントリを追加することによってカスタムマッピングを宣言します。 このエントリには、(1) マッピングされようとしている UDT の名前、および (2) UDT がマッピングしようとしている Java プログラミング言語の中のクラスの Class オブジェクトを含める必要があります。 そのクラスはそれ自身で特有のマッピングを含むようになります。なお、このクラスは、SQLData インタフェースも実装していなければなりません。

カスタムマッピングをサポートしている JDBC 2.0 ドライバによって生成された個々の Connection は、カスタムマッピングを追加するための空の型マップが組み込まれます。 この型マップは、java.util.Map インタフェースのインスタンスです。これは Java 2 プラットフォームの新しい機能で、java.util.Dictionary を置き換えます。 カスタムマップのエントリをこの型マップに追加するまでの間は、STRUCT および DISTINCT 値のすべての操作には、標準マッピングが使用されます (STRUCT 値の場合は Struct インタフェース、DISTINCT 値の場合は基盤となる型)。

次のコードでは、con に関連付けられた型マップが取り出され、新しいエントリが con に追加されます。ここで、con は Connection オブジェクト、ADDRESSES は SQL 構造化型です。 型マップが変更された後に、con の新しい型マップとして設定しています。

java.util.Map map = con.getTypeMap();
map.put("SchemaName.ADDRESSES", Class.forName("Addresses"));
con.setTypeMap();

Map オブジェクトの map は、con に関連付けられた型マップで、このコードの実行後には少なくとも、1 つ (マッピングがすでに追加されている場合は複数) のカスタムマッピングが含まれています。 (多くの場合、クラスを生成するツールを使用して) Addresses クラスを作成しておきます。 SQLData インタフェースを実装していないクラスを提供するのは誤りです。 Addresses クラスには、SQLData が実装されており、ADDRESSES の各属性に対応するフィールドが存在します。ADDRESSES 型の値が Java プログラミング言語のメソッドで操作されると、デフォルトで Addresses クラスのインスタンスにマッピングされます。 別の型のマップが明示的にメソッドに渡されない場合は、接続に関連付けられている型マップが、デフォルトの型マップになります。

UDT の名前は、完全に修飾された名前でなければなりません。 一部の DBMS では、catalogName.schemaName.UDTName の形式が使用されます。 しかし、多くの DBMS では、この形式は使用されていません。たとえば、カタログ名を含めずにスキーマ名が使用されます。 各 DBMS に適した形式を使用してください。 DatabaseMetaDatagetCatalogsgetCatalogTermgetCatalogSeparatorgetSchemas、および getSchemaTerm メソッドを使用すると、DBMS のカタログ名、スキーマ名、カタログとして好ましい語句、およびカタログ名とテーブル名の間に使用されている区切り文字に関する情報を取得できます。

既存の型マップを修正する代わりに、アプリケーションで別の型マップに置き換えることができます。 次のコードに示すように、ConnectionsetTypeMap メソッドを使用します。 新しい型マップを作成し、その型マップに 2 つのエントリ (それぞれは、SQL UDT 名およびその型の値のマッピング先のクラスを持つ) を追加します。次に、Connection の con に関連付けられた型マップとして新しい型マップをインストールします。

java.util.Map newConnectionMap = new java.util.HashTable();
newConnectionMap.put(
     "SchemaName.UDTName1", Class.forName("className1"));
newConnectionMap.put(
     "SchemaName.UDTName2", Class.forName("className2"));
con.setTypeMap(newConnectionMap);

これで、Connection オブジェクトの con にもともと関連付けられていた型マップは、Map オブジェクトの newConnectionMap に置き換わります。 newConnectionMap は、次に置き換えられるまで、カスタム型マップとして使用されます。この例では、新しい型マップを作成するときに、HashTable クラスのデフォルトのコンストラクタが使用されています。 このクラスは、Java 2 プラットフォーム API で提供されている java.util.Map の実装の 1 つです。その他の実装を使用することもできます。

前述のいくつかの例では、接続に関連付けられた型マップが、追加のマッピングを組み込むように変更されたり、まったく異なる型マップとして設定されました。 いずれの場合も、JDBC の型と Java プログラミング言語の型をカスタムマッピングするという点では、接続の型マップがデフォルト値になります。 次の例では、別の型マップを使うメソッドを提供することによって、接続の型マップを置き換える方法を示します。

メソッドの実装に UDT のカスタムマッピングを含めるかもしれない場合には、型マップを指定するメソッドと指定しないメソッドの 2 つのバージョンを用意します。 型マップをメソッドに渡した場合には、その型マップが、接続に関連付けられた型マップの代わりに使用されます。 たとえば、ArraygetArray および getResultSet メソッドには、型マップを指定するメソッドと指定しないメソッドがあります。 型マップがメソッドに渡された場合は、その型マップを使用して配列要素がマッピングされます。型マップが指定されていない場合は、接続に関連付けられた型マップがメソッドで使用されます。

メソッドに型マップを渡すと、同じユーザ定義の型の値に別のマッピングを設定できます。 たとえば、2 つのアプリケーションが同じ接続を使用し、同じ列の値を操作している場合、一方は、接続に関連付けられた型マップを使用し、他方は適切なメソッドに引数として渡した別の型のマップを使用することができます。

次のコードでは、新しい型マップを作成し、ArraygetArray メソッドにパラメータとして渡しています。

java.util.Map arrayMap = new java.util.HashTable();
arrayMap.put("SchemaName.DIMENSIONS", Class.forName("Dimensions"));
Dimensions [] d = (Dimensions [])array.getArray(arrayMap);

2 行目で、新しい型マップ arrayMap に、完全に修飾された SQL 構造化型の名前 (SchemaName.DIMENSIONS) および Java クラスオブジェクト (Class.forName("Dimensions")) のエントリが与えられています。 この結果、Java の Dimensions 型と SQL の DIMENSIONS 型の間にマッピングが確立されます。 3 行目では、arrayMap が型マップとして指定され、この Array オブジェクトの内容のマッピングに使用されます。基本型は、SchemaName.DIMENSIONS です。

getArray メソッドでは、array で指定された SQL3 ARRAY 値の要素が生成されます。このとき、各要素は、arrayMap で指定されているマッピングに応じてマッピングされます。 つまり、各 DIMENSIONS 値の属性を Dimensions オブジェクトのフィールドにマッピングすることによって、Schema.DIMENSIONS 型の値である各要素が、Dimensions クラスのインスタンスに変換されます。 配列の基になっている型が arrayMap で命名されている UDT 名と一致しない場合は、ドライバによって、配列の要素が標準的なマッピングに応じて変換されます。 また、getArray メソッドに型マップが指定されていない場合は、ドライバでは、接続の型マップで指定されているマッピングが使用されます。 その型マップに Schema.DIMENSIONS のエントリが存在しない場合は、ドライバでは標準的なマッピングが代わりに使用されます。



[目次] [前の項目] [次の項目]

Copyright © 1999, Sun Microsystems, Inc. All rights reserved.