3

添付されたエンティティRequestFactoryを永続化するには、各リクエストで同じものを使用する必要があります。EntityManager

実装に基づいて独自の Factory クラスをまとめましたThreadLocalが、リソースを適切に解放する方法がわかりません (たとえば、リクエストが終了したことを確認して を呼び出す方法close())。

完全な J2EE/CDI に頼ることなく、単一の EntityManager が特定の ServletRequest 全体で確実に使用されるようにする簡単な方法はありますか? 必要に応じてそのルートをたどりますが、特に GWT に付属する軽量の開発サーバーを引き続き使用したいので、物事をシンプルに保つことを望んでいました。

4

3 に答える 3

6

GWT Google GroupBobVからのフィードバックに基づいて、私が最終的に思いついたものを次に示します。

EntityManager のスレッド ローカル ホルダーを作成します。EntityManager を取得する必要がある場合は、エンティティでこれを参照してください。

public class ThreadLocalEntityManager
{
    private static ThreadLocal<EntityManager> holder = new ThreadLocal<EntityManager>();

    private ThreadLocalEntityManager()
    {
    }

    public static EntityManager get()
    {
        return holder.get();
    }

    public static void set(EntityManager em)
    {
        holder.set(em);
    }
}

次に、リクエストの初期 EntityManager を設定するフィルターを作成します。

public class PersistenceFilter implements Filter
{
    protected static final Logger log = Logger.getLogger(PersistenceFilter.class.getName());
    private EntityManagerFactory factory;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException
    {
        factory = Persistence.createEntityManagerFactory("my_persistence");
    }

    @Override
    public void destroy()
    {
        factory.close();
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException
    {
        EntityManager em = factory.createEntityManager();
        ThreadLocalEntityManager.set(em);

        EntityTransaction tx = em.getTransaction();
        tx.begin();

        try
        {
            chain.doFilter(req, res);
            tx.commit();
        }
        catch (Exception e)
        {
            tx.rollback();
        }
        finally
        {
            log.info("closing EntityManager: " + EMF.entityManager());
            em.close();
        }

    }
}

次に、フィルターを /gwtRequest URL パターンに適用します。

<filter>
    <filter-name>PersistenceFilter</filter-name>
    <filter-class>com.example.PersistenceFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>PersistenceFilter</filter-name>
    <url-pattern>/gwtRequest</url-pattern>
</filter-mapping>

ここには欠陥があることに注意してください。基になるコードで使用されているかどうかに関係なく、このサーブレットを通過する各リクエストに対して EntityManager が作成されます。おそらく、より堅牢になり、要求された場合にのみ EntityManager (およびトランザクション) を遅延して作成する可能性があります。

しかし、これまでのところ、このコードはRequestFactory. 改善のための提案は大歓迎です。

注: この経験から、このような CDI の一部を実装しようとするよりも、おそらく完全な CDI に移行する価値があることがわかりました。このプロジェクトでは、そのような移動に利用できる時間がありませんでした。

于 2011-02-15T16:25:36.593 に答える
4

DynaTableRf サンプル アプリは、サーブレット フィルターを追加してweb.xmlファイルに永続化コンテキストを設定することで、同様のことを行います。または、RequestFactoryServletdoPost()をサブクラス化し、そのメソッドをオーバーライドして、返さEntityManagerれたfinallyときにブロック内を破棄することもできsuper.doPost()ます。

于 2011-02-14T14:20:38.137 に答える
2

Spring を使用している場合は、OpenEntityManagerInView サーブレット フィルターを web.xml に追加するだけです。

<filter>
    <filter-name>entityManagerFilter</filter-name>
    <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>entityManagerFilter</filter-name>
    <url-pattern>/gwtRequest</url-pattern>
</filter-mapping>
于 2012-08-16T06:45:31.273 に答える