Morphia と
Spring Data for MongoDB のどちらを使うか? を検討している。要求は次のとおり。
- 多態性 (polymorphism) に対応していること
- インスタンス変数を持つ Enum を扱えること
Spring Data のドキュメントやコードをざっと見た限り、多態性には対応していないようだ。一方、 Morphia は
ドキュメントで説明しているように、この要件を満たす。そこで、Morphia を試すことにする。
ここでいう多態性とは?
抽象クラスやインタフェースのレベルで永続オブジェクトを操作できること。例えば、クラスA、B、C が次のような関係にあるとする。
このとき、db.find( A.class ) のように、B と C を区別せずに読み出したり検索したい。
なぜ Morphia は多態性を扱えるか?
ドキュメント内の className という特別なプロパティに Java のクラス名を保存しているから。例えば、Java のクラス B の完全修飾名が org.example.B だとすると、B オブジェクトを MongoDB に保存した場合、ドキュメントの JSON 表現は以下のようになる。
この仕組みによって、データベースからドキュメントを読み出したときに、どのクラス型の Java オブジェクトを生成すればよいかを(Morphia が)判断できる。多態性を扱う必要がない場合など、この className プロパティを保存しないように設定することもできる。
テスト
以下に示すコードでは、import 文、コンストラクタ、setter/getter を略す。MongoDB のデータベースを test、コレクションを polymorphism とする。
ドメインモデルのクラスは以下のとおり。Java クラスと MongoDB コレクションとの対応付けを @Entity アノテーションで行う。@Id アノテーションは MongoDB の _id プロパティへの対応付けを示し、org.bson.types パッケージで定義された ObjectId 型にしておくと Morphia が
自動的に値を割り当てる。
注意すべき点は、多態的に操作したい抽象クラスもコレクションに対応付けておかねばならないことである。
インスタンスの保存と読み出しの簡単なコードを以下に示す。
get では個々の具象クラスを指定して読み出している。find では A 型のインスタンスをすべて読み出している。元のコレクションが空だとすると、listA.size() は3になる。
Mongo シェルで db.polymorphism.find() して、コレクションに保存されたインスタンス(ドキュメント)の JSON 表示を見てみる。
Morphia の多態的操作について、最も基本的な動作を試した。今後、検索や更新についても試していく予定。
リソース: