#広義のORM論
@suke_masa さんのスライド、
https://www.slideshare.net/masatoshitada7/java-or-jsug
に触発されて、
もしも自分がアーキテクチャーの決定に全責任を持つとした場合、かつ、与件としてRDBMSとJavaを使うとした場合に、ORMに何を選定するか?現時点の解を出しておきたい。
開発者のスキルレベルにもよるが、そこそこのレベル(標準的という意味)だと仮定した場合に、現時点での優先順位は以下になるかな…
1.MyBatis
2.Doma
だいぶ離れて、JPA・・・
自前のDAOは無いな。
##◆まずMyBatisのメリットは「現実的なアプローチを採っていること」
どれか一つドキュメントを読むならこれを読んで欲しい。
http://www.mybatis.org/mybatis-3/ja/sqlmap-xml.html
この中にも、
「MyBatis は「データベースは必ずしも希望通りに定義されている訳ではない」という思想に基づいて設計されています。 すべてのデータベースが完全な第三正規形あるいは BCNF なら最高ですが、実際はそうではありません。 また、たったひとつで全てのアプリケーションに適合できるようなデータベースを作ることができたら素晴らしいですが、これも現実とは異なります。」という記述があります。
デメリットは、定義がXMLに寄せてあるので、「このご時世にXML地獄なのか?」という印象を持たれること。
ただし、XMLによるマッピング定義の学習コストはさほど高くないと思う。黒魔術になるくらいならちゃんと書こうよ。という姿勢もある意味潔いかな。
SQLの知識は当たり前だが相当に求められる。(というよりもSQLの知識を活かしやすい)
##◆Domaも魅力的である・・・
SQLファイルを一発書いたら、それをDomaからもRDBMSのプロンプトからも実行できる2-Way-SQLはやはり圧倒的な安心感がある。ピンチになったらヒント句書いておけばなんとかなるしw
SQLの知識を素直に活かせるという意味ではDomaはMyBatisと通じるものがある。ただし、Domaは元々はDomainを定義することに重きを置いており、現実世界の実用性から見るといくつかの機能不足がある。
MyBatisと比べた場合に、Association(関連するエンティティ)の紐づけ管理を、アプリ側の責務に寄せているのが個人的には残念。ただし、これは得られた結果をいい感じにDomainオブジェクトに詰め直す処理をJavaで書けば済む話なので、MyBatisのマッピング方言に慣れるか?Javaでマッピングを書くかは、最終的には好みの問題な気もする。
##◆JPAは厄介だw
JPA自体も厄介だが、さらに話をややこしくするのが中途半端にJPAやHibernateを使ったことがある輩がプロジェクトで変な動きをし出すと収拾がつかなくなる。
しかしながら、”由緒正しい標準である”という紛れもない事実は大きいので、ハマりどころと、それを避けるには結局どうすれば良いのか?というのは知っておいた方が良い。
ひとことで言うと、永続性コンテキストと関連やFetch戦略のオプションが複雑過ぎてコントロールしきれないということだと思う。すごい優秀なメンバーばかりで新規にテーブル設計もできるならJPAは最適解かもしれないが、そのような状況があまりないという現実を見据えるとやはり仕様がToo Muchだと思う。
皮肉なことに過去のプロジェクトではHibernateを使っていたが、なんとか乗り切るために、Hibernateの良さを殺す使い方をしていた。
まずは、Daoは永続性コンテキストから切り離した状態でEntityを返すことにしていた。従って、LazyLoadは使えない。
突き詰めると、Databaseは色々な形でデータを取り出したいというニーズに対応したものなので、ORMで隠蔽化する際にはある程度手間を掛けてマッピングせざるを得ないというのが現実である。
ところがJPAはこれをある意味真っ向から勝負してメタ定義一発でSQLを自動生成するというアプローチで解決を試みている。しかし現実にはメタ定義でモデルの関係性を定義しきれるものではなく、
JPQL、NativeQuery、Criteria、そして、JavaEE7では永続性コンテキストにアサインされないコンストラクタ式をサポートするという多様なアプローチで凌ごうとしている。
(実はアプリが単純であれば、JPQLでなんとかなるので、SpringJPAを使うとほぼノンコーディングでCRUD出来る。実際、チュートリアルレベルでは私もJPAは愛用しているw。しかし、現実の開発業務はそんなに簡単ではないので、様々な選択肢の中からチョイスすることになる。)
関連(OneToOneとかOneToMany)については、明らかにライフサイクルをともにするものに限りつけることを許可する。それ以外は、JPQLで明示的にFetchしてねという方針になっていく。
そうすると結局はSQL書いたほうが良いのでは?という話になる。
Qiitaで炎上したSQLオジサンの主張もあながち間違っていないwww
ちなみに、JPAでもNativeSQLがあるから良いじゃんという意見もあるが、あれはEntityにマッピングする場合には、永続性コンテキストを使うことには違いないので、永続性コンテキスト固有の厄介さとは無縁になれない。
更に言うと、永続性コンテキストを実質無効化して、NativeSQLを使うならばJPAにする意味がほとんど無い…
尚、JPAについてはこの辺の記事が非常に役立ちます。
http://enterprisegeeks.hatenablog.com/entry/2015/02/16/080922
##◆まとめ◆
結局、JPAに一番文字数を割いてしまった…。
永続性コンテキストを否定することを前提としたが、永続性コンテキストに載った状態で、ドメインロジック書くとJavaオブジェクトのミューテーターを呼べばよしなにJPAが面倒みてくれるのは非常に魅力的ではある。
ただし、世の中がイミュータブルに流れる中では、ミュータブルなオブジェクトを管理することに重きを置いていたJPAは時代遅れ(成熟する前に時代が変わってしまった)なのかもしれない。
案外JPAが好きだったのか、オレ?