S2EJB3UnitのProxiedObjectResolver
S2EJB3UnitのassertEntityEqualsではエンティティをリフレクションしてデータを読み取りますが、Lazy Loadingされるエンティティをよみとるためには永続プロパイダごとにLazy Loadingで利用されるプロキシから実体を取得する処理が必要です。
そこでS2EJB3UnitではProxiedObjectResolverというインタフェースを用意して、使用する永続プロバイダことに実装を用意してもらおうと思っています。たとえばHibernateを使う場合、次のようなクラスのインスタンスをS2EJB3UnitにDIします。(HibernateのバージョンでAPIが少し違うかも)
public class HibernateProxiedObjectResolver implements ProxiedObjectResolver { public Object unproxy(Object proxy) { if (proxy instanceof HibernateProxy) { return ((HibernateProxy) proxy).getHibernateLazyInitializer() .getImplementation(); } return proxy; } }
TopLinkの場合はProxyの実体を解決するためのAPIがよくわからないんですけど無理やりすればこんな感じ?どうもフィールドアクセスでもプロパティアクセスでも_toplink_getで始まるメソッドができているみたいです。こいつを呼び出してやると一応Lazy Loading(TopLinkではインダイレクションというらしい)されたオブジェクトがプロキシのフィールドにセットされます。これでOKかどうかは微妙です。
public class TopLinkProxiedObjectResolver implements ProxiedObjectResolver { private static Pattern pattern = Pattern.compile("^_toplink_get.+[^_vh$]"); public Object unproxy(Object proxy) { if (proxy instanceof TopLinkWeaved) { for (Method m : proxy.getClass().getMethods()) { if (pattern.matcher(m.getName()).matches()) { if (m.getParameterTypes().length == 0) { MethodUtil.invoke(m, proxy, new Object[] {}); } } } } return proxy; } }
http://d.hatena.ne.jp/bluerabbit/20060511#1147356961
ということで、id:bluerabbitさん、S2EJB3Unitを使ってみるというのはどうですか(^^
あと、HibernateProxiedObjectResolverはHibernateに依存するのでS2Hibernate-JPAに入れてもらえたらなぁと思っています。S2EJB3Unitはs2hibernate-jpa.diconを自動的に読み込むのでHibernateProxiedObjectResolverの定義はs2hibernate-jpa.diconにあらかじめ定義されてると便利なんですがどうでしょう?
ところで、どなたかTopLink入門記とかどうですかw。