連載 役に立つ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にマッピング |
|
サンプルアプリケーションの設計 |
|
「連載 役に立つXMLツール集」 |
- QAフレームワーク:仕様ガイドラインが勧告に昇格 (2005/10/21)
データベースの急速なXML対応に後押しされてか、9月に入って「XQuery」や「XPath」に関係したドラフトが一気に11本も更新された - XML勧告を記述するXMLspecとは何か (2005/10/12)
「XML 1.0勧告」はXMLspec DTDで記述され、XSLTによって生成されている。これはXMLが本当に役立っている具体的な証である - 文字符号化方式にまつわるジレンマ (2005/9/13)
文字符号化方式(UTF-8、シフトJISなど)を自動検出するには、ニワトリと卵の関係にあるジレンマを解消する仕組みが必要となる - XMLキー管理仕様(XKMS 2.0)が勧告に昇格 (2005/8/16)
セキュリティ関連のXML仕様に進展あり。また、日本発の新しいXMLソフトウェアアーキテクチャ「xfy technology」の詳細も紹介する
|
|