連載 役に立つXMLツール集(6)
CastorでオブジェクトをRDBにマッピング

www.netpotlet.com
原田洋子
2004/4/9

サンプルアプリケーションの設計

 本記事では最終的に、図3に示すHTMLを出力するアプリケーションを作成します。表中の情報はすべてデータベースから取得したものです。

図3 アプリケーションの実行結果(クリックで拡大します)

 なお、これから紹介するサンプルは次の環境で動作を確認しています。

  • JDK 1.4.1_06(Linux版)
  • Castor 0.9.5.3
  • PostgreSQL 7.4.2
  • Eclipse 2.1.2

開発手順

 Castor JDOを利用した開発手順はデータベースのテーブルに相当するJavaクラスの定義から始めるのが一般的ですが、本連載第3回でデータバインディングを試したので、今回はスキーマの定義から始めることにします。手順は図4に示します。

図4 開発手順


スキーマ定義とデータベースのテーブル定義

 最初にスキーマ定義とテーブルをどのように作るかを考えます。スキーマ定義とテーブル構成のどちらを先に考えるのかはケースバイケースでしょう。すでにデータベースにテーブルとデータがあってこれを操作するプログラムを作りたい場合や、新規に作るので制約がない場合などで違ってくるはずです。このサンプルは新規に作るので特に制約はありませんが、テーブル定義を考えるところから始めました。スキーマ定義の方がより柔軟にさまざまな構成に対応できるので、スキーマ定義をテーブルに合わせることにしたためです。

 このサンプルでは商品リストを扱うので、図5に示すテーブル構成にしました。この3つのテーブルはリスト1のcreate_table.ddlを使って作っておきます。なお、各テーブルのカラムの意味は表2〜4のようになっています。

図5 データベースのテーブル構成

リスト1 create_table.ddl(別ウインドウで表示します)

カラム名 意味
id 識別子
category_id categoryテーブルのこのidのデータへの参照
price_id priceテーブルのこのidのデータへの参照
sample サンプル画像のファイル名
name 商品名
date 入荷日
description 説明
表2 goodsテーブル

カラム名 意味
id 識別子
name カテゴリ名
表3 categoryテーブル

カラム名 意味
id 識別子
cost 仕入れ値
retail 小売値
表4 priceテーブル 

 次はこのようなテーブルに相当するスキーマ定義を考えます。XML文書にはルートに当たる要素が1つ必要なので、goodsList要素を設けました。goodsList以下に複数のgoods要素がある構成です。そして、このスキーマをコンパイルしたときに生成されるクラス構成は図6のようになるはずです。

図6 商品リストのクラス図

 そこで、リスト2に示すスキーマgoods.rngを作りました。これはRELAX NGによる定義で、これをTrangを使ってW3C XML Schemaに変換した後、CastorのSourceGeneratorでクラス定義を生成します。リスト2のようにスキーマを定義するとXMLインスタンスはリスト3のように書けます。

リスト2 goods.rng(別ウインドウで表示します)

リスト3 goods.xml(別ウインドウで表示します)

スキーマコンパイル

 スキーマ定義ができたので、コンパイルしてクラス定義を生成します。このとき、リスト4に示すAntのビルドファイルを使ってCastorのSourceGeneratorを実行しました。リスト4の18〜24行目がSourceGenerator実行のためのcastorターゲットです。このターゲットは実行前に26〜31行目のtrangターゲットを実行するようになっているので、RELAX NGによる定義をW3C XML Schemaによる定義に変換する作業も同時に行ってくれます。

 このビルドファイルは図7に示すディレクトリ、ファイル配置になっていることを想定しています。また、リスト3のgoods.xmlをMSV(本連載「第5回 スキーマコンバータ/バリデータ/ビジターパターン」参照)で検証できるようにもなっています。

 Antを実行するには、

 パッケージ・エクスプローラー → build.xml選択 → 右ボタン →
 Antの実行

とすると図8のウィンドウが開くので、ここで実行ボタンをクリックします。2回目以降はツールバーの外部ツール実行ボタンをクリックするだけで、前回と同じターゲットを実行できます。

図7 スキーマファイルとXML文書の配置


図8 Ant実行のウィンドウ(クリックで拡大します)

 Antの実行により、

  Category.java
  CategoryDescriptor.java
  Detail.java
  DetailDescriptor.java
  GoodsList.java
  GoodsListDescriptor.java
  Goods.java
  GoodsDescriptor.java
  Price.java
  PriceDescriptor.java

が生成されるので、次のようにしてEclipseの表示を更新するとクラスが表時されると同時にコンパイルされます。

 パッケージ・エクスプローラー → nymphプロジェクト選択 →
 右ボタン → 最新表示

リスト4 build.xml(別ウインドウで表示します)

データベース接続設定ファイルとマッピングルールの作成

 次にデータベース接続に必要な設定を記述するXML文書とマッピングルールを定義するXML文書を作ります。これらはアプリケーションから参照されるので、参照するアプリケーションと同じパッケージに置いて、クラスローダ経由で読み込みます。このサンプルではデータベース接続の設定ファイルをconfig.xml(リスト5)、マッピングルールを記述するファイルをmapping.xml(リスト6)という名前にしました。

 リスト5のconfig.xmlはプーリングなどは行わない、シンプルな接続を定義しています。JDBC URLを見ると分かるように、データベース名はnymphです。リスト6のmapping.xmlがO/Rマッピングの要となるマッピングルールの定義です。難しい文書構造ではないので、ファイルを眺めるだけで直感的に分かるのではないでしょうか。マッピングルールではクラスとそのフィールドをどのようにマップするかを定義します。

 Castor JDOの場合、クラスはテーブルに、フィールドはカラムにマップされます。また、フィールドの各変数に対するgetter/setterメソッドがあることが前提になっているので、SourceGeneratorを使わずに、自分でクラス定義する場合は必ずgetter/setterメソッドを定義するか、マッピングルールにgetter/setterに相当するメソッドの指定を追加します。sql要素のtype属性で指定した型はCastor JDO独自のマッピングルールによって適当なJavaの型に変換されます。

 さて、リスト6のmapping.xmlを見ると5行目でJdoGoodsという自動生成されたクラス以外のものをマッピングしています。このクラスが必要になったのはマッピング過程で問題が起きたためです。date型のマッピングです。

 Castor JDOはSourceGeneratorが生成したクラスをリレーショナルモデルにマッピングすることは、あまり考慮していないようです。このため、date型はXMLモデルからマップされるとorg.exolab.castor.types.Date型になる一方で、リレーショナルモデルではjava.util.Date型が要求されるという矛盾が起きます。このような問題を解決するCastor流のやり方はSourceGeneratorにバインディング情報を与えて、適当な型のフィールドが生成されるようにすることです。

 しかし、このサンプルではオブジェクトモデルのところでXMLモデルからリレーショナルモデルへの流れが途切れるのを逆手にとり、Goodsクラスを継承したリスト7のJdoGoodsクラスを定義し、リレーショナルモデル側はこれを参照することで問題を回避することにしました。

 アプリケーションを作る前に、JdoGoodsクラス、config.xml、mapping.xmlの3つを用意しておきます。JdoGoodsはcom.netpotlet.nymphパッケージのクラスとして定義します。config.xmlとmapping.xmlはアプリケーションからクラスローダを使って参照されるので、テストアプリケーションと同じパッケージ階層(ディレクトリ)に置きます。ここでは、com.netpotlet.testパッケージなので、config.xmlはこのパッケージのクラスと同じディレクトリに作ります。mapping.xmlですが、このファイルはconfig.xmlのmapping要素を参照して暗黙的に読み込まれます。サンプルを動かしてみると、com.netpotletのディレクトリ階層に置かないといけないようです。従って、次のようにして3つのファイルを作ります。

JdoGoods.java
 パッケージ・エクスプローラーでパッケージ(com.netpotlet.nymph)選択 →
 右クリック → 新規 → クラス → 名前(JdoGoods) →
 スーパークラス(com.netpotlet.nymph.Goods)→ 終了

config.xml
 パッケージ・エクスプローラーでソース・フォルダー(src)選択 →
 右クリック → 新規 → パッケージ →
 パッケージ名(com.netpotlet.test) → 終了

 パッケージ(com.netpotlet.test)選択 → 右クリック → 新規 →
 ファイル → ファイル名(config.xml)→ 終了

mapping.xml
 パッケージ・エクスプローラーでソース・フォルダー(src)選択 →
 右クリック → 新規 → ファイル → 親フォルダー選択(図9)→
 ファイル名(mapping.xml)→ 終了

図9 mapping.xmlファイルの作成


リスト5 config.xml(別ウインドウで表示します)

リスト6 mapping.xml(別ウインドウで表示します)

リスト7 JdoGoods.java(別ウインドウで表示します)

 これでアプリケーションの設計と必要な準備が終わりました。次ページではいよいよアプリケーション本体の作成に入ります。(次ページへ続く

2/3 アプリケーション作成

 Index
連載 役に立つXMLツール集(6)
CastorでオブジェクトをRDBにマッピング
 

O/Rマッピングツール概要
Castor JDOとは
Castorの入手とセットアップ

サンプルアプリケーションの設計

 

アプリケーション作成
まとめ
サンプル・ダウンロード&参考サイト

 

「連載 役に立つXMLツール集」


XML & SOA フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

HTML5+UX 記事ランキング

本日月間