GWT RequestFactory:如何在每个请求中使用单个EntityManager

Geo*_*old 3 gwt code-injection entitymanager cdi requestfactory

为了得到RequestFactory持续连接的实体,我需要确保我用同样的EntityManager每个请求.

我根据ThreadLocal实现拼凑了我自己的Factory类,但我不确定如何正确释放资源(例如,如何知道请求已完成并调用close()).

是否有一种简单的方法可以确保在给定的ServletRequest中使用单个EntityManager而无需使用完整的J2EE/CDI?如果必须,我会采取这种方式,但我希望保持简单,特别是因为我想继续使用GWT附带的轻量级开发服务器.

Geo*_*old 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后创建一个过滤器,为请求设置初始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();
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

然后将过滤器应用于/ 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>
Run Code Online (Sandbox Code Playgroud)

请注意,这里存在一个缺陷 - 为每个通过此servlet的请求创建一个EntityManager,无论它是否由底层代码使用.它可能会变得更加健壮,并且只有在请求时才会以某种方式懒洋洋地创建EntityManager(和事务).

但到目前为止,这段代码似乎运行良好RequestFactory.对改进的建议非常欢迎.

注意:这种经验告诉我,它可能值得转向全面的CDI,而不是试图实现它的一部分.在这个项目期间,我只是没有时间进行这样的行动.