注: この章の内容は、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
クラスは、クラスのインスタンスを生成する static セクション (static 初期設定子) を記述しておき、ロード時に DriverManager
クラスを使って登録します。ロードされるタイミングで DriverManager
クラスに登録されます。 したがって、ユーザは通常 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 つ以上のドライバを記入していると、DriverManager
クラスはそれらをロードしようと試みます。以下のコードは、‾/.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);