Tcl BlendとJDBCによるデータベース接続

 JDBC(Java DataBase Connectivity) (*1)とは、サン・マイクロシステムズ社が提唱している、 Javaプログラムから各種のRDBMS(リレーショナルデータベース管理システム) に接続する際のプログラミング・インターフェース(API) で、その機能はJ2SEのjava.sqlパッケージ及び一部 javax.sqlパッケージで定義されています。 J2SEの他に各RDBMSベンダから提供されるJDBCドライバと呼ばれるJARアーカイブを入手すれば、 どのベンダのRDBMSにも同じAPIを使って接続できるという利点があります。 Javaからのデータベースアクセスは、事実上常にJDBCを使って行うことになります。

(*1) サンの公式見解では、JDBCは何かの略語ではなく、そういう名前の技術なんだ、 ということになっていますが、 当サイトでは率直に言って、どっちだろうが興味はないです。 「JDBCは、JDBCです」というよりはいいかなと思って、あえて書きました。

 JDBCドライバが提供されているRDBMSといえばオラクルのOracle、 サイベースのAdaptive Server EnterpriseとAnywhere、 IBMのDB2やCloudscape、 オープンソースのRDBMSではPostgreSQLやMySQLなどがありますが、 今回はPostgreSQLのJDBCドライバを使ってPostgreSQLデータベースにアクセスする例をご紹介します。
 PostgreSQLのJDBCドライバは本体処理系のソース配布に同梱されており、 JDKのjavacコンパイラを使ってビルドできます。 JARアーカイブpostgresql.jarができればビルドは成功です。このファイルは、 どこに置いても構いませんが、 /usr/local/pgsql/lib が一番分かりやすい場所でしょう。 後は環境変数CLASSPATHにこのJARアーカイブを追加しておけば、 JDBCドライバがロードできるようになります。

●サンプルJava版
 Javaでのサンプルです。ここではJDBCについて1から説明は省きますが、 ごくごく基本的な例ということでコードだけ載せてみました。 JDBCの詳細については専門の書籍をチェックしてみてください。

import java.sql.*;

public class PgJdbcTester {
  public static void main (String args []) {
    try {
      // PostgreSQL JDBC driverをロードします。
      Class.forName("org.postgresql.Driver");
    } catch(ClassNotFoundException ex){
      System.err.println(
        "おおっと! PostgreSQL JDBC Driverが見つかりません。");
      System.exit(1);
    }

    String user = "urano";
    String password = "";

    try {
      Connection conn =
        DriverManager.getConnection(
          "jdbc:postgresql://localhost:5432/udb", user, password);
      System.out.println ("接続されました。");
      // SQL文(DML文)を作ります。
      Statement stmt = conn.createStatement ();
      // SELECT文の場合はexecuteQuery()を実行します。
      String sql = "select * from items where item_class = 'LCX'";
      ResultSet rset = stmt.executeQuery (sql);
      while (rset.next ()){
        System.out.println(rset.getString(1) + "\t" +
                   rset.getString(2) + "\t" + rset.getString(3));
      }
      // 結果セットを解放
      rset.close();
      // SQL文を解放
      stmt.close();
      // データベースから切断して、完了。
      conn.close();
    } catch(SQLException ex){ // SQLの構文エラー、RDBMSのエラーなどの例外
      System.err.println("おおっと! " + ex);
      ex.printStackTrace();
    }
  }
}
// end.

●サンプルTcl Blend版
 同じコードのTcl Blend版です。 例外を処理していないせいもありますが、随分簡潔になっていますね。 処理の流れ自体は全く同じです。

package require java

if {[catch {java::call Class forName "org.postgresql.Driver"} err]} {
    puts "おおっと! PostgreSQL JDBC Driverが見つかりません : $err"
    exit
}
set url "jdbc:postgresql://localhost:5432/udb"
set conn [java::call java.sql.DriverManager getConnection $url "urano" ""]

puts "接続されました。"
# SQL文(DML文)を作ります。
set stmt [$conn createStatement]
# SELECT文の場合はexecuteQuery()を実行します。
set sql "select * from items where item_class = 'LCX'"
set rset [$stmt executeQuery $sql]

while {[$rset next] != 0} {
    puts "[$rset {getString int} 1]\t\
    [$rset {getString int} 2]\t[$rset {getString int} 3]"
}
# 結果セットを解放
$rset close
# SQL文を解放
$stmt close
# データベースから切断して、完了。
$conn close
# end.

 いきなり本題から外れますが、 上のコードの赤字部分に今までと違うメソッドのコールが書かれています。 これはメソッドシグネチャと呼ばれるものです。 Javaはメソッドのオーバーロード (同じ名前で異なるデータ型の引数をもつメソッドを複数定義すること) ができるので、この例での java.sql.ResultSet.getString() のように、getString(int a) と getString(String a) という数が同じで異なる型(クラス)の引数をとる場合、 それらのどのメソッドをコールしたいのかを明示的に指定する仕組みです。 通常はStringが優先されてしまうので、 ここでのように、getString(int a)のメソッドをコールしたい場合には

  $rset {getString int} 1
このような書き方をします。
 本題に戻って、Tcl Blendを使えばJDBCドライバを使ってこのように Tcl/TkからRDBMSにアクセスできるのですが、これ、予想通りかなり遅いのです。 もともとJavaクラスのロードというのがかなり重い処理なので、 JDBCしかAPIのないRDBMSに無理やりTclから接続したいというような場合を除き、 アプリケーションの実用としてはいまいち使えないでしょう。
 また通常は、JDBCでRDBMSに接続する一番基本的な部分は何らかの形で Javaクラスとしてまとめておき、 Tcl Blendから呼ぶならそのクラスを使うほうがすっきりしていると思います。 このページではネイティヴャな書き方をしてみましたが、 あんまり実用的とは言えますまい、というのが感想です。

拡張レビュー分室 top
(first uploaded 2001/10/18 last updated 2002/08/19, MISUMI URANO - KOUKEN HEIJIMA)