[PR]今日のニュースは
「Infoseek モバイル」


zxJDBCによるデータベース操作

zxJDBC
 Pythonの世界には、 Python Database APIという、 Python言語からRDBMS(リレーショナルデータベース管理システム) を操作するための拡張モジュールを開発する際のAPI規約があり、 普通のPython(CPython)からOracle、Sybase、MySQL、PostgreSQL などのRDBMSに接続してデータを操作するためのモジュールがたくさん開発されています。 DBモジュールの分室でご紹介している cx_Oracle、PygreSQL、MySQLDBなどは、それらの有名な一部です (どれがどのRDBMSに接続するモジュールかは名前を見れば一目瞭然ですよね?)。
 同じことはJavaでも可能です。但しJavaの場合は既にJDBCという今度はJava言語のAPI がありますから、 JDBCをさらにPython DB APIでラップしたモジュールがあればよいわけです。 その標準の地位にあるのがzxJDBCと呼ばれるモジュールで、 これはJythonのバージョン2.1から本体に同梱されています。 zxJDBCを使うと、Jythonからデータベース操作をするときに、 前のページのようにいちいちJDBCのクラスを使う必要はなく、 たいへん便利に使うことができます。

 zxJDBCでデータベース操作ができる環境は、 JDBCでデータベース操作ができる+Jython+zxJDBCです。 先述したように、Jython 2.1以降にはzxJDBCが入っています。 そうでない場合は上記のzxJDBCのホームページから入手できます。
 JDBCでデータベース操作ができる環境とは、 というのはこのサイトの趣旨から大きく脱線するので省きますが、 おおざっぱーにいうとRDBMSのネイティブクライアント (OracleならSQL*Plus、MySQLならmysqlコマンドとか)でデータベースサーバに接続できること、 J2SE 1.3とか1.4とか、及び各RDBMSに合ったJDBCドライバを入手していることです。 ここではWindows XP上でローカルホストのMySQLにJython 2.1付属のzxJDBCで接続を試しました。

とりあえず接続して、検索する

#
# zxjdbctest1.py
# Jythonでzxjdbcのテスト(表の全件SELECT)
# 2003/01/08
#
from com.ziclix.python.sql import zxJDBC

con = zxJDBC.connect("jdbc:mysql://localhost/udb", None, None, "org.gjt.mm.mysql.Driver")
# optionally
#>>> db = zxJDBC.connect(d, u, p, v, CHARSET='iso_1')

cur = con.cursor()
sql = """
SELECT SHITEN_CODE, SHITEN_NAME
  FROM SHITEN
"""
cur.execute(sql)
rset = cur.fetchall()
print "%d行のデータが 見つかりました。" % cur.rowcount
for e in rset:
  print "%-5s %-30s" % e
print "ok."
cur.close()
con.close()
# end.

本当にデータベースに接続して、全件を検索するSELECT文を発行するだけのサンプルです。 接続するには、zxJDBC.connect関数を使います。 あとは、普通のPython Database API準拠のモジュールと同じです。 詳しくは、「DBモジュール」の分室をご覧下さい。

データソースを使ったり、バインド変数を使ったりする

#
# zxjdbctest2.py
# Jythonでzxjdbcのテスト
# ・接続に引数の代わりにデータソース(DataSource)を使用
# ・検索条件にバインド変数を使用。zxJDBCのプレースホルダはqmark(?)です。
# 2003/01/08
#
import sys
from com.ziclix.python.sql import zxJDBC
print zxJDBC.paramstyle

params = {}
params['serverName'] = "localhost"
params['databaseName'] = "udb"
params['user'] = "urano"
params['password'] = ""
params['port'] = 3306
try:
  con = apply(zxJDBC.connectx, ("org.gjt.mm.mysql.MysqlDataSource",), params)
except zxJDBC.DatabaseError, e:
  print "データベースに接続できませんでした。"
  print "原因:" + e[0]
  sys.exit(1)

cur = con.cursor()
sql = """
SELECT SHITEN_CODE, SHITEN_NAME
  FROM SHITEN
 WHERE SHITEN_NAME = ?
"""
cur.execute(sql, ("福岡",))
rset = cur.fetchall()
if cur.rowcount > 0:
  print "%d行のデータが 見つかりました。" % cur.rowcount
  for e in rset:
    print "%-5s %-30s" % e
  print "ok."
else:
  print "該当データが見つかりませんでした。"
  print "sad."
cur.close()
con.close()
# end.

 今度のサンプルは、まずデータベース接続にデータソース を使っています。データソースを使う主なメリットは、 接続ぷーリングを標準で行うため、パフォーマンスが一般によいことです。 そのために、zxJDBC.connectx関数に、 データソースのクラス名と、 そのインスタンスに渡すプロパティをディクショナリにしたものを引数として渡しています。

 今度は接続時のエラー処理もしてみましょう。 接続エラーが起きたときはサンプルのようにzxJDBC.DatabaseError (Javaのjava.io.SQLExceptionみたいなもの)が発生するので、 適切に処理を書いてやればよいだけです。

 はてさて、WHERE句で条件を指定したSQL文を発行するときなどに大変重宝するのがバインド変数です。 Python DB APIではモジュールごとにバインド変数の位置をSQL文中で指定するためのプレースホルダの記法を選ぶことができますが、 「print zxJDBC.paramstyle」すると「qmark」と表示されるとおり、 zxJDBCのプレースホルダはハテナマーク(?)です。 これはJDBCの記法と同じ(java.io.PreparedStatementで使うプレースホルダと同じ) なので、分かりやすいと思います。

セクションのサブメニューに戻る
(first uploaded 2003/01/08 last updated (not ever))