これまで、RDB と Object-Relational (O/R) マッピングフレームワークを使ってきた。具体的には、Object-XML マッピングも扱える Castor を利用してきた。しかし、コンポジットオブジェクトの扱いに苦労した。
コンポジットパターンとは?
Wikipedia (日|英)を参照されたし。要するに、自己参照ループを持つようなクラス構造で、インスタンスはツリーを成す。
以下に、Wikipedia 日本語版の例を少し変更したコンポジットパターンのクラスを示す。一部のメソッドは省略した。
さて、このようなコンポジットパターンのオブジェクトを RDB に保存するにはどうすればよいか? 簡単ではない。以下のような課題に直面する。
- 階層構造を読み出すには、ツリーをたどりながら複数回の検索を行うか、1回の検索で関連するオブジェクトをすべて取得してアプリケーション側で階層を構成するか。保存する場合は逆の手順が必要。
- Composite 役と Leaf 役を一つのテーブルに格納しようとすると、各クラスに固有のプロパティはそれ以外のクラスのインスタンスのカラムで NULL になってしまう。
- Composite 役と Leaf 役をそれぞれ独自のテーブルに保存するには、O/Rマッピングフレームワークが多態性をサポートしていなければならない(part 1 参照)。Component 役が抽象クラスで継承関係をもマッピングしようとするならば、データベースレコード継承(関係継承)が必要。
テストコード
上に示したコンポジットパターンを Morphia を使って MongoDB に出し入れしてみる。
コンポジットオブジェクトを保持するクラスを用意する。
テストコードは以下のとおり。
保存されたドキュメント
上のコードで保存されたドキュメントの JSON 表現を見てみる。
Folder 型のオブジェクトが入れ子状になってツリー構造を成しているのがわかる。オブジェクトの読み出しも問題なく行えた。
リソース:
- Composite pattern - Wikipedia - (English) http://en.wikipedia.org/wiki/Composite_pattern - (Japanese) http://ja.wikipedia.org/wiki/Composite_%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3