読者です 読者をやめる 読者になる 読者になる

至高のORMを求めて放浪

Java ORM

まえがき

この記事はオブジェクト関係マッピング(ORM)を実装する方法がどうこうという話ではなく、単に愚痴です。

事の起こり

社内の新規プロジェクトで

  1. 「具体的な機能要件もUIも決まっていないが、新規公開サービスについてある機能(といってもそれなりに複雑なWebアプリを一つ必要とする程度にはヘビー)だけ先にお前が実装してみてくれ」というタスクが出される
  2. そんな事言っても機能要件とDBテーブル定義ぐらいは最低限何とか決めておいてくれと頼んだものの、その辺は適当にやっておけと言われる(この辺は色々と事情があるので、仕方が無い面もあるが・・・)
  3. とりあえず似たような機能を持つ既存システムのテーブル定義を拡張したテーブルを使用したり(というかこの段階では既存システムのテーブル定義を流用するという話だった)、DBアクセスの無いモックDAO実装を作って開発実装を進める。この頃までは、DAOを抽象化しておけばある程度テーブル定義が変わっても他の部分に影響を及ぼさずに何とか行けるだろうと楽観視してた。
  4. 先行公開の数週間前になって、具体的な機能要件やテーブル定義が決定。これまで作ってきたコードのうち、DAOの定義も含めて半分ぐらいを一気に叩き潰して再実装する必要があることが判明
  5. 俺涙目(いまココ)

ということで、DAO(とその他関連箇所)を書きなおすために様々なORMを触り、実装してはまた捨て・・・という賽の河原的な作業をやっていたので、せっかくなのでまとめてみます(実装コード等は勘弁)。

触ってみたORMとその感想

ActiveObjects

Active Objects: Wiki: Home — Java.net

InterfaceへのAnnotationをベースにした軽量ORM。特にJPAである必要はなくテーブル構成もろくに決まっておらず、しかもなるべく簡単に手早く実装する必要があるプロジェクトなので、先ず最初に検討したのがコレ。しかし、以下の理由から断念。

  • EntityManager#migrateを実行すると、該当データベース中に存在するActiveObjectsとは関連の無いものを含む全てのTableが全てDropされた・・・Javadocにもそういう記述は無いし、ちょっとこれは暴れ馬過ぎる
  • 公式ドキュメントを見ると最新バージョンは0.8.2だが、maven central repositoryを見ると0.9.21が出ている模様。0.9台ではAnnotaionクラスが大幅に変わっている様子だが、どうもその辺を解説したドキュメントが(もちろん英文含めて)見つからない。
rufiao persist

rufiao/persist · GitHub

良さそうではあるものの、業務システムでの使用実績がいまいち見つからなかったので、涙を飲んで断念。あと、もう1年以上ソースがコミットされていないのが気になる。

Commons DbUtils

JDBC Utility Component

古参のJDBCユーティリティ。最新バージョンの更新日は2012-07-20。枯れたと思っていたけど結構ちゃんとメンテされてるもんだな。
ORMではないものの、単純なselect文についてはJava BeanへMappingしてくれる。ただし、TableのRelationをそのままネストしたBeanへMappingするような機能は無いため、Nested Beanについては手作業でコーディングする必要がある(過去に機能追加要求で度々議題に上がっているものの「ウチはORM作ってるわけじゃない」という理由でRejectされてる。)。あと、更新系クエリについては完全に手で書く必要が有るので煩雑。

EclipseLink

EclipseLink Home

ここまで調べてみて、もう「軽量」ORMには自分の探しているモノが無いかも・・・ということで、EclipseLinkを試す。
Annotationベースで設定できるはJPQLはネイティブSQLと比較すれば簡単に書けるわ、さらにはDDLも自動生成してくれるわで申し分無かったものの・・・ここらへんの時期にテーブル実装がカッチリ決まる
一応、こちらからもJPAアノテーションを元にして生成したテーブル定義を提案したものの、蹴られて終了。

JPAが真価を発揮するのはJavaコードからテーブル定義を生成するような場合であり、既存テーブル定義が存在する場合にはJPA使ってもメリットは薄れるよなあ・・・・工数に余裕があればなんとかなると思うものの、涙を飲んで見送り。

MyBaits

MyBatis 3 | イントロダクション

ということでテーブル定義が決まったことで、ネイティブSQL定義を呼び出すタイプのORMを探す方向へ切り替える。先ず最初に思いつくのがMyBaits。
怒涛の設定量(この辺)に死にそうではあるものの、MyBaits GeneratorでBeanとMappingファイルを生成するか、あるいは既存BeanにAnnotationを付けて何とかするか、検討中。

Doma

Doma - Domaプロジェクトへようこそ

ドキュメントを読む限り、自分が抱えてる要求にぴったり合うのはDomaな気がしてきた・・・ちょっと実装してみて感触を探る。

追記: Doma - よくある質問によるとネストしたBeanに対するマッピングには対応して居ないとのこと・・・今回は期日も迫ってるし、準備不足のままでDomaを導入してしまうより、Commons DbUtilsでガリガリと生SQL書いたほうがいいかなあ。

安西先生・・・・行き当たりばったりじゃなくて、ちゃんと設計したいです。


参考文献

まあ、ORM実装がどうこういう問題じゃ無いよね本質的に。

失敗の本質―日本軍の組織論的研究 (中公文庫)

失敗の本質―日本軍の組織論的研究 (中公文庫)