Guice WebExtensions Persist ?
正式名称がこれであっているのかよくわからないのですが、GuiceとHibernateを組み合わせたものみたいです(今後はJPAもサポートするらしいです)。
http://www.wideplay.com/guicewebextensions2
Guice WebExtensions Persistの一機能であるDynamic Findersを使うとインタフェースとアノテーションだけでDAOが作れるらしいです。(検索のメソッドはDAOだけでなくエンティティにも持たせられます。これをDDDとか言っていますが、ちょっと違うような。)
http://www.wideplay.com/dynamicfinders
機能は多くないです。ざっとこんな感じ。
動かしてみました。
サービスのクラス
Hibernateと連携するトランザクションのインタセプターは用意されています。@Transactionalで使えます。
public class EmpService { @Inject EmpAccess empAccess; @Transactional public List<Emp> findAll() { return empAccess.findAll(); } @Transactional public Emp findByName(String name) { return empAccess.findByName(name); } }
DAOのインタフェース
public interface EmpAccess { @Finder(query = "from Emp") List<Emp> findAll(); @Finder(query = "from Emp e where e.empName = :empName") Emp findByName(@Named("empName") String name); }
テストコード
public class EmpAccessTest extends TestCase { EmpService service; @Override protected void setUp() throws Exception { super.setUp(); Injector injector = Guice.createInjector(PersistenceService .usingHibernate().across(UnitOfWork.TRANSACTION).addAccessor( EmpAccess.class).buildModule(), new AbstractModule() { protected void configure() { bind(Configuration.class).toInstance( new AnnotationConfiguration() .addAnnotatedClass(Emp.class)); } }); injector.getInstance(PersistenceService.class).start(); service = injector.getInstance(EmpService.class); } public void testFindAll() throws Exception { assertEquals(2, service.findAll().size()); } public void testFindByName() { assertNotNull(service.findByName("hoge")); } }
追記
取得は@Finder使えばいいとして、更新・追加・削除の処理はどすればいいんでしょうか...。インタフェースに書けないですね。EmpAccessの抽象クラスを作ってそこでSessionに直接アクセスすればいいのかなと思ったんですが、これは認めれられていないようでした。