jarファイル1つで動作するJavaのORM DomaとActiveObjects
jarファイル1つで手軽に試せるJavaのORM DomaとActiveObjectsのサンプルをT2を使い作りました。
Doma
以前カンファレンス時に、id:taediumさんに「Doma触ってサンプル作ります」と言ったのでいつまで待たせるんだ!と怒られないように作成しました。
T2 + Guice + Doma
詳細な使い方等は、id:c9katayamaさんが解説してくれていますので、こちらをご覧下さい。
http://d.hatena.ne.jp/c9katayama/20091011/1255244389
補足
あとGuiceとDomaにはTransaction機能はないので、SpringのTransactionInterceptor等のトランザクション機能を使ってみたがGuiceのサンプルなのにSpringも出てくると、T2 + Guice + Doma + Springとちょっと複雑なサンプルになると思い、独自トランザクションにしてあります。
GuiceとDomaの連携
連携させるには、DataSourceやDialectをGuiceより取得するところと、Domaが生成するDaoImplをGuiceに登録すればOKです。
ここでGuiceにはSingletonS2Contanerのようなクラスは存在しないので、SingletonなModuleを用意し
DomaConfigや通常のModule installの際に以下のようにする方法があります。
// DomaConfig内 protected static Injector injector = Guice.createInjector(DomaModule .getInstance()); // 通常のモジュールインストール時 install(DomaModule.getInstance()); // DataSourceとDialectはSingleton登録 bind(DataSource.class).to(H2DataSource.class).in(Scopes.SINGLETON); bind(Dialect.class).to(HsqldbDialect.class).in(Scopes.SINGLETON);
ひとまずT2のGuiceAdapterの方でSingletonなInjectorを返すような関数を提供することにしましたので
DomaConfigでは以下のように実装します
public class GuiceDomaConfig extends DomaAbstractConfig { @Override public DataSource dataSource() { Injector injector = GuiceAdapter.getSingletonGuiceInjector(); return injector.getInstance(DataSource.class); } @Override public Dialect dialect() { Injector injector = GuiceAdapter.getSingletonGuiceInjector(); return injector.getInstance(Dialect.class); } }
早速、中村さんが対応してくれたようです。
http://d.hatena.ne.jp/taedium/20091016/p2
最新版にのちほど対応してみます。DaoImplを自前で生成してtoInstanceでしょうか。
Domaのコンセプト
- 暗黙的な規約よりも明示的な設定を重視する
- 他のライブラリに依存しない
- できる限り実行時ではなくコンパイル時にエラーを検出する
- できる限りキャッシュしない
- わかりやすいエラーメッセージを出力する
Domaのコンセプトは上記の通りで、個人的には他ライブラリ依存が無い事とコンパイル時にエラーを検出するところが良いと思います。
Domaの感想
Domaはなんといってもjarファイル1つで動作させるところが手軽です。
環境面でいつくか制限がありますがEclipseユーザには、向いていると思いますし、Domaが自動生成するソースが.apt_generatedフォルダを見ればすぐ分かるのも素敵ですね。
S2Daoを使った事がある人であれば、2WaySQLに慣れていると思いますのでDomaの2WaySQLにすんなり移行出来るのではないかと思いました。
T2自体も他のライブラリと組み合わせて使うのでT2との相性は良いと思いました。
http://doma.sandbox.seasar.org/
id:taediumさん応援してます!
ActiveObjects
https://activeobjects.dev.java.net/
activeobjectsは、Doma同様jarファイル1つで動作して、migration機能もあり軽量なORMです。
T2との連携に関しては特に設定はありません。
H2で動かすためにH2用のProviderを作りましたが、これもそのうち本体側に取り込まれると思います。
Transaction
aoには、Transaction機能をTransactionクラスという抽象クラスとして提供されます。
構文は以下の通りで、匿名クラスを作成し使用します。
Account result = new Transaction<Account>(manager) { public Account run() throws SQLException { Account back = getEntityManager().create(Account.class); back.setBalance(0); back.save(): return back; } }.execute();
凄くシンプルですので、Guice + Doma サンプルの方のTransactionはaoのTransactionを参考に作成しました。
Query
Query実行に関してもシンプルなのですぐ理解出来ますね。
// id指定で取得 Person[] persons = manager.find(Person.class, "id = ?", id); // 名前のlike検索 Person[] persons = manager.find(Person.class, "name like ?", "%" + name + "%");
メソッドチェーンを使用し複雑な問い合わせも可能。
Person[] drinkers = manager.find(Person.class, Query.select().where("age > ?", 21).limit(10));
OneToMany, ManyToManyアノテーション
public interface Company extends Entity { // ... @OneToMany public Person[] getEmployees(); } public interface Person extends Entity { // ... @ManyToMany(Authorship.class) public Book[] getBooks(); }
T2 + ActiveObjects
DIコンテナ無しでActiveObjectsのサンプルも作りました、T2プロジェクトのsamplesにコミットしてあります。
Eclipseプロジェクトになっていますので、coしてT2ActiveObjectsServerStartを実行するとサンプルが動作します。
Domaとaoの共通点
- jarファイル1つで動作
- DIコンテナ不要
- 信頼性がある
- dev.java.net(最近はDOS攻撃で落ちていたり..)で開発されている(最近は更新頻度が低いようですね)
- id:taediumさんが開発されている
まとめ
JavaでのORMを検討してる方は、DomaやActiveObjectsを検討してはいかがでしょうか。