注: この章の内容は、Addison Wesley 社より Java シリーズの 1 巻として出版された『JDBCTM API Tutorial and Reference, Second Edition: Universal Data Access for the JavaTM 2 Platform』(ISBN 0-201-43328-1) に基づいて作成したものです。
DriverManager クラスは、ユーザとドライバの間で機能する従来の JDBC の管理レイヤです。このドライバマネージャは、使用可能なドライバを追跡し、データベースと対応するドライバ間の接続を確立します。加えて、DriverManager クラスは、ドライバのログイン時間の制限やログの出力およびメッセージの追跡なども行います。
javax.sql パッケージ、つまり JDBC 2.0 標準拡張機能 API では、データソースに接続するための好ましい代替手段として DataSource インタフェースを提供しています。しかし、DriverManager 機能も引き続き、DataSource 実装をサポートするドライバとともに使用できます。
単純なアプリケーションの場合、DriverManager クラスで一般のプログラマが直接使用する必要がある唯一のメソッドは DriverManager.getConnection です。その名前が暗示しているように、このメソッドはデータベースへの接続を確立します。アプリケーションは、Driver のメソッド connect と同様に DriverManager のメソッドである getDriver、getDrivers、および registerDriver を呼び出せますが、ほとんどの場合、DriverManager のクラスにデータベースとの接続に関する詳細を管理させる方がよい結果になります。
DriverManager クラスは、DriverManager.registerDriver メソッドの呼び出しによってそれ自身で登録した Driver クラスのリストを維持します。すべての Driver クラスで、ロード時にクラスのインスタンスを生成し、それを DriverManager クラスに登録するための static セクション (static 初期設定子) を記述する必要があります。したがって、DriverManager.registerDriver は通常、ユーザによって直接呼び出されることはなく、ロード時に Driver クラスによって自動的に呼び出されます。Driver クラスがロードされ、自動的に DriverManager に登録されるには、以下の 2 通りの方法があります。
Class.forName メソッドを呼び出す方法。これは明示的にドライバクラスをロードします。これは外部のどのセットアップにも依存していないので、DriverManager フレームワークを使用する場合には、この方法でドライバをロードすることを推奨します。acme.db.Driver クラスをロードするコードは以下のとおりです。
Class.forName("acme.db.Driver");
ロード時にインスタンスを生成し、そのインスタンスをパラメータとして指定して (そうする必要がある) DriverManager.registerDriver を呼び出すように、acme.db.Driver が記述されていた場合、そのドライバは、DriverManager のドライバリスト内に格納され、接続を作成するために使用可能となります。
Driver クラスを java.lang.System プロパティ jdbc.drivers に加える方法。これは DriverManager クラスがロードするドライバのクラス名のリストで、コロンで区切られています。DriverManager クラスは初期化時に、システムプロパティ jdbc.drivers を検索し、そこに 1 つ以上のドライバがユーザによって入力されていた場合、それらのドライバをロードしようとします。以下のコードは、~/.hotjava/properties に 3 つのドライバクラスを記述しておく方法を示します (HotJava は起動時にシステムプロパティ内にこれらをロードします)。
jdbc.drivers=foo.bah.Driver:wombat.sql.Driver:bad.test.ourDriver
DriverManager メソッドへの最初の呼び出しは、これらのドライバクラスを自動的にロードします。
ドライバをロードするこの第 2 の方法では、持続的な環境をあらかじめ設定しておく必要があることに注意してください。この環境が設定されていると確信できない場合は、Class.forName メソッドを呼び出して、それぞれのドライバを明示的にロードする方が安全です。いったん DriverManager クラスが初期化されると、jdbc.drivers プロパティリストは再チェックされないため、この方法も特定のドライバをロードするのに用いる正しい方法となります。
これら両方の場合において、DriverManager.registerDriver を呼び出して自らを登録することは、新たにロードされた Driver クラスの責任です。前述のとおり、これはクラスのロード時に、自動的に行われる必要があります。
セキュリティ上の理由から、JDBC 管理レイヤはどのクラスローダがどのドライバを供給したのかを追跡しています。そして DriverManager クラスが接続を開始するときに、ローカルファイルシステムから得られるドライバ、または接続のための要求を発行しているコードと同一のクラスローダから得られるドライバだけを使用します。
Driver のクラスがロードされ、DriverManager クラスに登録されると、それらはデータベースとの接続を確立するために使用可能となります。接続要求が DriverManager.getConnection メソッドに対する呼び出しによって行われると、DriverManager は、順次各ドライバをテストして、接続を確立できるかどうか確認します。
複数の JDBC ドライバが与えられた URL へ接続できる場合が起こり得ます。たとえば、リモートのデータベースに接続する場合、JDBC−ODBC ブリッジドライバ、JDBC- 汎用ネットワークプロトコル間ドライバ、またはデータベースのベンダーが供給しているドライバを使用することが可能でしょう。このような場合、DriverManager はその URL に正常に接続できることがわかった最初のドライバを使用するので、ドライバがどの順序でテストされるかは重要です。
DriverManager はまず、登録された順序でドライバを使用しようと試みます。jdbc.drivers にリストされているドライバは、常に最初に登録されています。DriverManager は、接続を開始しようとしているコードと同一のソースからロードされていない限り、信頼されないコードのドライバをすべて無視します。
DriverManager は、それぞれのメソッド Driver.connect を順次呼び出すことによってドライバをテストし、ユーザが始めにメソッド DriverManager.getConnection に渡した URL をそれらのドライバに渡します。URL を認識した最初のドライバが接続を行います。
この方法は、一見したところ非効率的に見えるかもしれません。 しかし、実際には、数ダースものドライバが同時にロードされることはありえないため、2、3 のプロシージャ呼び出しと接続ごとの文字列比較しか必要ではありません。
以下のコードは、JDBC−ODBC ブリッジドライバのようなドライバによって接続をセットアップするために通常必要とされるコードの一例です。
Class.forName("jdbc.odbc.JdbcOdbcDriver"); //loads the driver
String url = "jdbc:odbc:fred";
Connection con = DriverManager.getConnection(
url, "userID", "passwd");
変数 con は、SQL 文の作成および実行に使用できるデータソース fred への接続を表します。
JDBC 2.0 標準拡張機能 API を追加することによって、DataSource オブジェクトをデータソースとの接続の確立のために使用できます。DriverManager も引き続き使用できますが、DataSource オブジェクトは DriverManager と比較していくつかの点で優れているため、より良い代替手段となります。ただし、Enterprise JavaBeans のコンポーネントを記述している開発者は、DriverManager ではなく DataSource オブジェクトを常に使用してください。適切に実装された DataSource オブジェクトを使用することが、プールされ、分散トランザクションに参加できる接続を取得する唯一の方法となります。
すべての DriverManager メソッドは static として宣言されています。つまり、それらのメソッドは、特定のインスタンスではなくクラス全体に対して実行されます。実際、DriverManager のコンストラクタは、ユーザがインスタンスを生成できないように、private として宣言されています。論理的には、DriverManager クラスのインスタンスは 1 つです。これは、次のコード行のように、DriverManager でメソッドを修飾することによってメソッドを呼び出すことを意味します。
DriverManager.setLogWriter(out);