GWT RequestFactory:如何针对每个请求使用单个EntityManager [英] GWT RequestFactory: how to use single EntityManager per request

查看:94
本文介绍了GWT RequestFactory:如何针对每个请求使用单个EntityManager的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了获得 RequestFactory 坚持连接的实体,我需要确保我为每个请求使用相同的 EntityManager

我基于 ThreadLocal 实现将我自己的Factory类拼凑在一起,但我不确定如何正确地释放资源(例如,如何知道请求已完成并调用 close())。

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

这是我最终想出的结果, / google-web-toolkit / XY6EaPqatygrel =nofollow noreferrer> GWT Google Group 和 BobV

为EntityManager创建一个线程本地持有者;

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

private ThreadLocalEntityManager()
{
}

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

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


$ / code>

然后创建一个过滤器,将初始EntityManager设置为请求:

  public class PersistenceFilter implements Filter 
{
protected static final Logger log = Logger.getLogger (PersistenceFilter.class.getName());
私人EntityManagerFactory工厂;

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

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

$ b @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();

尝试
{
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>

请注意,这里存在一个缺陷 - 为通过此servlet的每个请求创建一个EntityManager,不管它是否被你的底层代码使用。它可能会变得更强大,并且只是在被请求时才会懒惰地创建EntityManager(和事务)。



但是到目前为止,这段代码似乎与 RequestFactory 。改进建议非常受欢迎。注意:这个经验告诉我,将CDI转换为全功能可能是值得的,而不是试图实现这样的部分。在这个项目中,我只是没有时间做这样的动作。

In order to get RequestFactory to persist attached entities, I need to ensure that I use the same EntityManager for each request.

I cobbled together my own Factory class for this based on a ThreadLocal implementation, but I'm unsure how to properly release resources (e.g. how to know that the request has finished and call close()).

Is there a simple way to ensure that a single EntityManager is used throughout a given ServletRequest without resorting to full-on J2EE/CDI? I'll take that route if I must, but I was hoping to keep things simple, especially since I'd like to continue using the lightweight development server that comes with GWT.

解决方案

Here is what I ultimately came up with, based on feedback from the GWT Google Group, and BobV.

Create a thread-local holder for the EntityManager; reference this in your entities when they need to get an 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);
    }
}

Then create a filter that will set the initial EntityManager for the request:

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();
        }

    }
}

Then apply the filter to the /gwtRequest URL pattern:

<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>

Note that there is a flaw here- an EntityManager is created for each request that goes through this servlet, whether it's used by your underlying code or not. It could probably stand to be made more robust and somehow lazily create the EntityManager (and the transaction) only when requested.

But so far this code seems to work well with RequestFactory. Suggestions for improvements highly welcomed.

Note: this experience has taught me that it's probably worth moving to full-on CDI rather than trying to implement pieces of it such as this. I just didn't have the time available for such a move during this project.

这篇关于GWT RequestFactory:如何针对每个请求使用单个EntityManager的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆