Helmaでデータベースを使う | JavaScript | プログラミング

Helmaシリーズ第3回、今回の内容は、Helmaでデータベースを使う方法についてです。

  • データベース連携のための準備
  • helma.Databaseオブジェクトを使ったデータベースアクセス

HelmaにはO/Rマッピングが用意されています。O/RマッピングはSQLレスにプログラミングができることが魅力ですが、結論から言うと、私はhelma.Databaseオブジェクトを使った方法で目的を果たしました。テーブルをJOINするなど、既に書くべきSQLがわかっているのにO/Rマッピングの方法がわからず、調べるのに時間がかかりすぎてしまったからです。

という事情で、ここで説明する方法は、O/Rマッピングを使わない別の方法です。O/Rマッピングでの方法は、記事の最後に参考URLを掲載するので、そちらを参照してください。

データベース連携のための準備

例に使うテーブルの説明

まず、今回の例に使うデータベーステーブルについて説明します。シチュエーションはブログエントリーで、テーブルは2つ。ブログ記事を保管するENTRYテーブルと、投稿者を保管するAUTHORテーブルです。ブログといえば他にもカテゴリーやコメント・トラックバックなどの情報もありますが、今回はそれらについては割愛し、ブログ投稿と投稿者だけを扱うことにします。

ENTRYテーブルには投稿を識別する「ENTRY_ID」と投稿者(投稿の筆者)を表す「AUTHOR_ID」カラムを持ちます。また「AUTHOR_ID」カラムはAUTHORテーブルにもあり、「AUTHOR_ID」で投稿者の名前を引くことができます。

ENTRYテーブル
プライマリキー カラム名 データ型(長さ) 意味
ENTRY_ID INTEGER(11) 投稿の識別ID
  AUTHOR_ID CHAR(5) 投稿者の識別ID
  TITLE INTEGER(11) タイトル
  CREATED TIMESTAMP 投稿日時
AUTHORテーブル
プライマリキー カラム名 データ型(長さ) 意味
AUTHOR_ID CHAR(5) 投稿者の識別ID
  NAME VARCHAR 投稿者名

データベースにこの2つのテーブルをCREATEし、テスト用のレコードを数件登録しておきます。

JDBCドライバを入手

HelmaはJVM上で動くWebフレームワークです。データベースへのアクセスにはJDBCドライバを使います。使用するデータベースに応じたJDBCドライバを入手し、<Helmaのインストールディレクトリ>libext の下に置きます。

Helmaの設定ファイルを編集(db.properties)

私はHSQLDBを使いましたので、以下はHSQLDBの場合の記述例です。

# This is where you specify relational data sources to
# map Helma types to relational databases.
#
# If you want to define a data source just for one
# application, simply copy the db.properties file to
# the application directory.
#
# The actual mapping of types is done in the
# type.properties file in the prototype directories.
#
# More information about this file is available at
# http://helma.org/docs/guide/properties/db.properties/

# Properties of JDBC data sources
#myDataSource.url = jdbc:mysql://db.domain.com/space
#myDataSource.driver = org.gjt.mm.mysql.Driver
#myDataSource.user = username
#myDataSource.password = xyz

# HSQLDBの場合
dbconn.url = jdbc:hsqldb:hsql://hostname.domainname:9001/dbname
dbconn.driver = org.hsqldb.jdbcDriver
dbconn.user = username
dbconn.password = password

ファイルの準備ができたら、Helmaを起動しなおします。コンソールを見るとJDBCドライバのjarファイルにクラスパスを通していますね。これでJDBCドライバが使えるようになりました。

Starting HTTP server on port 8080
Serving applications from C:helma_home
Adding to classpath: C:helma_homelibexthsqldb.jar	<- ココ
Starting Helma 1.6.3 (November 25 2008) on Java 1.5.0_17

helma.Databaseを使ったデータベースアクセス

<Helmaインストールディレクトリ>modulesの下にはアプリケーションで使える有用なオプションモジュール(JSファイル)が用意されています。データベース接続に関するメソッドを備えたJavaScriptオブジェクト(global.helma.Database)が使えるモジュールは、coreDatabase.jsです。

オプションモジュールをアプリケーション(Rootディレクトリ下のhacファイル)から使えるようにするには、モジュールをHelmaアプリケーションのリポジトリに追加する、ということをします。リポジトリへの追加方法は2通りあります。

1.hacファイルで追加する

hacファイルの冒頭に、次の行を記述します。

書式:

  • app.addRepository(‘<オプションモジュールへのパス>’)

記述例:

app.addRepository('modules/helma/Database.js');

appオブジェクトは、グローバルオブジェクトのプロパティとして自動的にインスタンス化されているもので、アプリケーションの動作設定に関するプロパティやメソッドを参照・操作できます。オプションモジュールファイルへのパスはHelmaインストールディレクトリからの相対パスで指定します。

2.apps.propertiesで追加する

モジュールのリポジトリ登録をアプリケーション設定に書くこともできます。hacファイルが多くなったとき、各ファイルにapp.addRepositoryメソッドの行を書くのは面倒なので、こちらの方がおすすめです。app.propertiesに次のような設定行を追加します。

書式:

  • <アプリケーション名>repository.<1以上の数字>

記述例:

symple
symple.repository.1 = modules/helma/Database.js

「.1」の部分は、複数のオプションモジュールをリポジトリに追加するとき、互いが重複しないように番号をつけます。「symple.repository.0」は、暗黙にsympleアプリケーションのアプリケーションディレクトリで設定がなされているので、0は避けてください。

Database.jsのメソッド

リポジトリの追加ができれば、Database.jsにあるオブジェクトがhacファイルで使えるようになります。以下は、レコードの検索(SELECT文)のサンプルコードです。

(アプリケーションディレクトリRootselect.hac)

var db = helma.Database.getInstance("dbconn");
var sql = "SELECT ENTRY.TITLE, AUTHOR.NAME ";
sql += "FROM ENTRY, AUTHOR WHERE ENTRY.AUTHOR_ID = AUTHOR.AUTHOR_ID";

this.result = db.query(sql);

var str = "";
for (var i=0; i < this.result.length; i++) {
	str += "タイトル:" + this.result[i].TITLE;
	str += "投稿者:" + this.result[i].NAME;
	str += "<br />";
}

helma.Database.getInstanceはデータベースインスタンスを取得するメソッドです。引数にdb.propertiesに書いたデータベースソース名「dbconn」の文字列を渡せば、設定に書いたデータベースに接続できるDatabaseオブジェクトが返されます。

(HelmaインストールディレクトリmoduleshelmaDatabase.jsのgetInstanceメソッド)

/**
 * Get a Database instance using the Database source defined in the
 * application's db.properties file with the given name.
 * @param {String} name the name of the DB source as defined in db.properties
 * @return {helma.Database} a helma.Database instance
 */
helma.Database.getInstance = function(name) {
    return new helma.Database(app.getDbSource(name));
}

SELECT文の実行は、getInstanceメソッドによって取得したDatabaseオブジェクトのqueryメソッドで行います。SELECT文の文字列をqueryメソッドの引数に渡します。実行結果はオブジェクトの配列で受け取れます。

(HelmaインストールディレクトリmoduleshelmaDatabase.jsのqueryメソッド)

/**
 * Executes the given SQL statement. The result set is returned
 * as JavaScript Array containing a JavaScript Object for each result.
 * @param {String} sql an SQL query statement
 * @return {Array} an Array containing the result set
 */
this.query = function(sql) {
	// 省略
}

更新系のSQLの実行は、queryメソッドでなく、executeメソッドを使います。引数はSQL文の文字列で、実行結果として更新行数を数値(int)で受け取ります。

(HelmaインストールディレクトリmoduleshelmaDatabase.jsのexecuteメソッド)

/**
 * Executes the given SQL statement, which may be an INSERT, UPDATE,
 * or DELETE statement or an SQL statement that returns nothing,
 * such as an SQL data definition statement. The return value is an integer that
 * indicates the number of rows that were affected by the statement.
 * @param {String} sql an SQL statement
 * @return {int} either the row count for INSERT, UPDATE or
 * DELETE statements, or 0 for SQL statements that return nothing
 */
this.execute = function(sql) {
	// 省略
};

コミットやロールバックはどうするのか?ですが、Database.jsの中には該当するメソッドがありませんでした。その代わり、DatabaseオブジェクトからgetConnection()メソッドでコネクションが取れるので、自分でsetAutoCommit(false)し、commitやrollbackのメソッドを使えばよさそうです。これ以上の詳細は実験していないので今回は述べません。

まとめ

Helmaを解説するサイトではO/Rマッピングでの使い方の紹介ばかりです。O/Rマッピングでなければデータベースアクセスは難しいの?と思いながらHelmaのディレクトリをちょっと覗いてみたらjsファイルが見つかり、中を眺めてみたら簡単に使えそうで、使ってみたらすぐにできてしまってビックリというのが正直な感想です。O/Rマッピングを使わずに直接SQLを書きたい方の役に立てば幸いです。

(参考URL)