- PR -

JDBCドライバに関する疑問

1
投稿者投稿内容
ほまらら
ベテラン
会議室デビュー日: 2005/10/19
投稿数: 54
投稿日時: 2005-11-22 14:55
JDBCドライバって、
Class.forName("org.postgresql.Driver");
でクラスをロードした後に、
Connection _con = DriverManager.getConnection("url","user","password");
と続きます。
これはDriverManagerクラスのAPIによれば、DriverManagerクラスがjdbc.driversというプロパティを参照するから必要な手順らしいのですが、これって、なんでこんな構造をしているのでしょう?

普通は、各ベンダが供給するjarファイル内でDriverManagerクラスを拡張するなりConnectionクラスを実装するなりの形式になると思うのですが・・・。
Class.forNameをこんな使い方をしているのは、なにか訳でもあるんでしょうか?

この形式であれば各JDBCドライバのjarファイルが無い状態でもコンパイルまではできますが、
コンパイルが通ったところでjarファイルが無ければどうせ実行できないんだし・・・
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2005-11-22 15:31
各JDBCドライバでは Driver クラス(インターフェースだったかも)を継承しています。
Class.forName() でクラスを読み込むと、static イニシャライザで DriverManager に自身のシングルトンのインスタンスを登録します。
で、DriverManager の getConnection() 内で登録済みのドライバからその URL を受け付けるかどうか順に問い合わせるわけですね。
このような仕組みのおかげでコンパイル時に実際に利用する JDBC ドライバが必要なくなり、またロードするドライバを設定で変更できるようになります。
ロードするクラス名をハードコードしている限りは固定ですが。
ほまらら
ベテラン
会議室デビュー日: 2005/10/19
投稿数: 54
投稿日時: 2005-11-22 15:46
なるほど、getConnectionでurlから各jdbcを区別してましたか。
たしかに、そこしかチェックしようがないですね。
この変わった構造は、再コンパイルせずにJDBCドライバのバージョンを上げられるようにするための工夫ってところでしょうね。
未記入
ぬし
会議室デビュー日: 2004/09/17
投稿数: 667
投稿日時: 2005-11-22 16:18
このトリッキーな JDBC の仕組み嫌いです。本来、static イニシャライザはユーザーが意識しなくてもよい初期化を行うために、クラスがロードされたときに実行したいコードを書く場所でしょう。static イニシャライザを呼びたいからクラスをロードするというのでは順逆だと思います。しかし、他にうまい実装が思いつかないのも事実。せめてクラスロードという概念だけでもユーザーから隠蔽して欲しかったです。

コード:

    public static void DriverManager.load("com.my.driver") throws ClassNotFoundException;


こんな感じのメソッドを用意して、その内部で勝手にクラスをロードしてくれたら良かったのに。

最近は、各 JDBC ドライバ依存な DataSource を直接生成するようにしてしまいました。DataSource から Connection を取得するようにすると、コネクションプーリングをしてくれるので。DriverManager.getConnection() では、毎回データベースへの接続動作が発生してしまいますよね。

コード:

    SQLServerDataSource mds = new SQLServerDataSource();
    mds.setServerName("localhost");
    mds.setDatabaseName("Northwind");
    ...
    Connection cn = mds.getConnection();


SQL Server の場合はこんな感じです。ただ JNDI が面倒で、ドライバ依存な DataSource を直接 new しているのが ちと恥ずかしい。JNDI を使わずに JDBC ドライバに依存せず(開発時にドライバへの参照を必要とせず) DataSource を利用する簡単な方法ってないものかしら。
ほまらら
ベテラン
会議室デビュー日: 2005/10/19
投稿数: 54
投稿日時: 2005-11-22 16:34
おおっ、なるほど。そうすればJNDIを回避できましたか。
DataSourceに移行したいな〜と思いつつ、JNDIの存在に二の足を踏んでいたのですが、一歩進めそうです。
ソースの参照先がJavaの基礎知識から一歩はみ出るから却って保守性や可読性が悪くなる気もするし。
まあ、そうも言ってられないか・・・。
でもどうにもXML関係は苦手だ。SOAP−XMLでDOM使ってみたら処理がバカ遅くなったから、結局巨大なStringでやったような記憶が・・・。

山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2005-11-22 16:59
ちなみに JSR-88 で規定されている J2EE Application Deployment 仕様でも同じような設計で DeploymentManager というインスタンスを取得するようになってます。
http://java.sun.com/j2ee/1.4/docs/api/javax/enterprise/deploy/shared/factories/DeploymentFactoryManager.html#getDeploymentManager(java.lang.String,%20java.lang.String,%20java.lang.String)

http://www.jcp.org/en/jsr/detail?id=88

とにかく遠回りしてハードコードさせないようにという設計が好きなようで。
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2005-11-22 18:40
引用:

SQL Server の場合はこんな感じです。ただ JNDI が面倒で、ドライバ依存な DataSource を直接 new しているのが ちと恥ずかしい。JNDI を使わずに JDBC ドライバに依存せず(開発時にドライバへの参照を必要とせず) DataSource を利用する簡単な方法ってないものかしら。


私が良く使う方法ですが、CommonsのDBCPを利用しています。
サーブレットのinitメソッドでBasicDataSourceのインスタンスを生成して
ServletContextに登録しています。

TomcatのコネクションプーリングもDBCPで実装していますし、
そんなに品質も悪くないのではと思います。
1

スキルアップ/キャリアアップ(JOB@IT)