しいしせねっとわーくAmazon.co.jp アソシエイト
[Java] [J2EE] [SQLのメモ] [PostgreSQL用JDBC]

JDBCメモ

PostgreSQL 7.3系、7.4系のJDBCドライバ は別のところにあります。

こっちはJDBC全般のメモ予定 (書く暇ない・・・。)
Javaでデータベースにアクセスすることが出来ます。便利です。

もくじ?

  1. 環境
  2. バージョン
  3. JNDIとDataSource
  4. 特殊編 DatabaseMetaData
  5. JDBCをトレースする

JDOってなに?

[JDO]はJDBCの上でオブジェクトと関連する層のようです。

必要な環境

さてさて、データベース(DBMS)とプログラム、どうやって繋がっているのでしょう?
SQLコマンドとは何? と、不思議でした。
SQLは言語ではなくてコマンドなのです。それで、プログラミング言語のようなif とかループがありません。それで、プログラミング言語と組み合わせて使うという使い方ができあがったようです。コマンドなので、""で囲んで、シェルの実行のような感じで実行します。そして、戻ってきた値は、複数行、複数カラムありますので、ひとつづつ順番に getString()や getInt() 等のメソッドで取り出せます。

参考

JDBC (java.sun.com)
JDBC2.0&J2EEによるJavaデータベースプログラミング(JDBCを知っている人におすすめ?)

JDBCのバージョン

JDBCは、1.x 2.x 3.x の3つのバージョンがあります。
JDKのバージョンやJDBCドライバによって、どのレベルまで対応しているかは異なります。また、おなじバージョンでもオプションをサポートしているかいないかで、J2SEとJ2EEでもJDBCの範囲が異なります。

初期化する

まずConnection を取得する

Class.foeName(Driver class name); JDBCドライバをDriverManagerに登録する。
この他に java.lang.System の jdbc.drivers プロパティに記述しておく方法もある。

Connection con = java.sql.DriverManager.getConnection(URL,account,password);
con.createStatement();

効率よくConnectionを管理する場合(JDBC1.2以降)

Connection をつかってデータベースと接続するのには時間がかかります。つかわなくなったConnection をいくつか接続したままにして、次の利用のときに効率よく再利用することができます。
Connection.close() でDBサーバとの接続が切られるのではなく、一時保管されます。

javax.sql.DataSource というインターフェイスを使います。 これは、基本的にサーブレットエンジンなどのフレームワーク上でJNDIに登録して使うもののようですが、どうやって使うのでしょうか。
JNDIを知っている必要があるらしいです。
雑誌、書籍等では、この近辺の解説は、はぐらかされています。
J2EEの場合は、XMLファイル等に記述してJNDIに登録しますが、統一された方法はありません?。

とりあえず、依存する方法でどうなるのか調べてみた

まず、DataSource の準備

PostgreSQLの場合

String dbserver = "postgresql.example.com", dbname = "postgres", dbuser = "postgres", dbpass = "****";
org.postgresql.PostgresqlDataSource ds = new org.postgresql.jdbc2.option.PoolingDataSource(); // でいいのかな?
ds.setServerName(dbserver);
// ds.setPortNumber(xxx);
//ds.setDescription("xxxxx");
ds.setDatabaseName(dbname);
// ds.setUser(dbuser);
// ds.setPassword(dbpass);

pgsql/jdbc.html

それからDataSourceをJNDI へ登録

Hashtable env = new Hashtable();
env.put(いろいろ, あれこれ); // 謎
env.put(いろいろ, あれこれ); // 謎
Context ctx = new InitialContext(env);
ctx.bind("jdbc/いろいろ名前", ds);

これでいいのか?
次回、ctx から登録した名前で取り出す事ができるのかもしれない。

J2EEやServletサーバ(Tomcatなど) の場合には、ここまでのことは配備記述子(DD)といわれるXMLファイルで記述します。普通はこんなことする必要はありません。

JNDI から DataSource の取得

DataSoutce ds;
ctx = new InitialContext(env);
ds = (DataSource) ctx.lookup("jdbc/いろいろ名前");

受け取れたらしい。登録したDataSourceとたぶん同じものです。

DataSourceからConnectionの取得

Connection con = ds.getConnection(あれこれ);

ん〜、JNDIつかわなくてもいいような気もしてきた。 JNDIを使って効果がある場合というのは、プログラムとデータベースを完全に依存しないように分離する場合ですね。それから、コネクションプールを使いたい場合などもjava.sql.DriverManagerを使わずにこちらの方法を使うということなのでしょう。たぶん。

参考

Statement と PreparedStatementの違い

Connection con = 〜;
Statement st = con.createStatement();
として作ると、何でも実行できますが、一部文字の入ったデータを入れられないとかの問題もあったり。

PreparedStatementを使ってみると、パラメータへデータを指定するのに実体を指定できるので、文字列にすると都合のわるい文字なども含めることができます。
しかし、パッチ処理ができないのがちょこっと辛いかも。

XADataSource とは、分散したデータベースをサポートするもの。JDBC2.0から対応しているものもある。と、J2EEに書いてあった。

特殊編

で、メインで使うのは、Connection、Statement、ResultSet ですが、各種データベースのサポート状態等々を調べるのにMetaDataというクラス群があるようです。
例えば、Connectionには、getMetaData() というメソッドがあります。

java.sql.DatabaseMetaData

DatabaseMetaDataは、データベースやテーブルの一覧、状態などを取得するためのクラスです。

MetaDataをみていると、随所に catalog というものがありますが、これは何でしょう?

PostgreSQLの場合は、データベースの一覧のようです。接続しているデータベースも含め、psql -l で見ることのできる一覧が返ってきます。getCatalogTerm()でもcatalogはデータベースのことであるということがわかります。

catalog内はどうなっているのでしょうかね。 PostgreSQLの場合は、1つのデータベース内でも制御用と一般用の2種類のデータを持っています。これを区別するために ? schemaというものがあるようです。pg_catalog が管理用で、publicがデータ用かな。

テーブル一覧を取得する

ResultSet getTables(catalog,schema,tabletype) ですね。

PostgreSQLではカタログ名が入っていませんが、直した方がいいのかも。他にも、不足している項目がいろいろあります。

JDBCトレースフィルタの製作

Sun ONE Studio 4で、PostgreSQLのJDBCドライバとの相性がよろしくないようですね。そこで、どの機能がよくないのか調べるために、汎用のJDBCトレース機能を作ってみました。このJDBCトレース機能は、JDBCドライバと利用するソフトウェアの間に入って、JDBCドライバの代わりに動作します。

クラス net.siisise.sql.trace.Driver

URL trace:<Driverクラス>:<従来のjdbcURL> という形で、簡単に利用できます。たとえば、PostgreSQLであれば、 java.sq.DriverManager.getConnection("trace:org.postgresql.Driver:jdbc:postgresql://server.example.org/db",account,password); というような感じです。Class.forNameに関係する部分も含めてtraceドライバの中に入れてしまうことで、互換性は充分にあると思います。

SoftLibにあり。

詳細は、okome@しいしせねっと まで。

[しいしせねっと]