jarファイル1つで動作するJavaのORM DomaとActiveObjects

jarファイル1つで手軽に試せるJavaのORM DomaActiveObjectsのサンプルをT2を使い作りました。

Doma

以前カンファレンス時に、id:taediumさんに「Doma触ってサンプル作ります」と言ったのでいつまで待たせるんだ!と怒られないように作成しました。

T2 + Guice + Doma

T2 + Guice + Domaで構成されています。

詳細な使い方等は、id:c9katayamaさんが解説してくれていますので、こちらをご覧下さい。
http://d.hatena.ne.jp/c9katayama/20091011/1255244389

補足

あとGuiceDomaにはTransaction機能はないので、SpringのTransactionInterceptor等のトランザクション機能を使ってみたがGuiceのサンプルなのにSpringも出てくると、T2 + Guice + Doma + Springとちょっと複雑なサンプルになると思い、独自トランザクションにしてあります。

GuiceDomaの連携

連携させるには、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を検討してる方は、DomaActiveObjectsを検討してはいかがでしょうか。