warp-persist試す

と言っても,ここに書いてあるとおりにやっただけなんだけどさ。Dynamic Findersで,気になったところがあったんで,そこだけメモっとく。


Dynamic Findersってのは,@Finderアノテーションを付けたインターフェイスだけを作っておけば,実装いらずで検索用DAOが作れるっていうwarp-persistの機能のことだ。
こんな感じでFinderのコードを書いて,

import com.wideplay.warp.persist.dao.Finder;
import sample.entity.Blog;

import java.util.List;

public interface BlogFinder {
    @Finder(query = "select o from Blog o")
    List<Blog> getAllBlogs();
}

こんな感じで,Guicewarp-persist)に登録すると,Finderの実装がなくても使えるようになる。

public class BlogAppFactory {
    private static Injector injector;

    public static void init() {
        injector = Guice.createInjector(
                new BlogModule(),
                PersistenceService
                        .usingJpa()
                        .across(UnitOfWork.REQUEST)
                        .addAccessor(BlogFinder.class) // ← ここ
                        .transactedWith(TransactionStrategy.LOCAL)
                        .buildModule());
    }

    public static <T> T getInstacne(Class<T> clazz) {
        return injector.getInstance(clazz);
    }
}

一見便利そうに思えたんだけど,実装いらずは検索処理だけで,更新処理は実装がいるのだ。
更新用DAOってのは,こんなコードを書く(JavaEEによるリソース管理しないから,@Resourceアノテーションはないよ)。

import com.google.inject.Inject;
import com.google.inject.Provider;
import com.wideplay.warp.persist.Transactional;
import sample.entity.Blog;

import javax.persistence.EntityManager;

public class BlogDAO {
    @Inject
    private Provider<EntityManager> em;

    @Transactional
    public Blog create(String title, String link) {
        Blog blog = new Blog(title, link);
        em.get().persist(blog);
        return blog;
    }
}

つまり,検索用と更新用のDAOを用意するハメになるんで,めんどくせぇなぁ〜なんて思ったわけだ。

BlogDAO blogDAO = BlogAppFactory.getInstance(BlogDAO.class);
BlogFinder blogFinder = BlogAppFactory.getInstance(BlogFinder.class);


で,試したことは「BlogFinderをBlogDAOに実装したらどうなるか?」っての。やれば,できるんだけど,アノテーションとかどうなるのか,興味あったんで試してみた。結果はこう。

public interface BlogFinder {
    // @Finder(query = "select o from Blog o") → アノテーションは要らない
    List<Blog> getAllBlogs();
}

public class BlogDAO implements BlogFinder {
    @Inject
    private Provider<EntityManager> em;

    @Transactional
    public Blog create(String title, String link) {
        Blog blog = new Blog(title, link);
        em.get().persist(blog);
        return blog;
    }

    @Finder(query = "select o from Blog o") // ← 実装側にアノテーションが必要
    public List<Blog> getAllBlogs() {
        // 空実装でよい
        return null;
    }
}

んー,こんなだったら,あえてDynamic Findersを使わず,ふつーにJPAクエリを使った方がよさげだの。あまり異端なことしても,ついてくる人いなさそうだし。
それと,なるべくJavaEE風な記述のほうが,いろいろ便利な予感がする。:-D