【问题标题】:GWT RequestFactory: how to use single EntityManager per requestGWT RequestFactory:如何为每个请求使用单个 EntityManager
【发布时间】:2011-06-26 16:20:33
【问题描述】:

为了将RequestFactory 转换为persist attached entities,我需要确保对每个请求都使用相同的EntityManager

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

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

【问题讨论】:

    标签: gwt code-injection cdi entitymanager requestfactory


    【解决方案1】:

    DynaTableRf 示例应用通过添加一个 servlet 过滤器在其 web.xml 文件中设置持久性上下文来执行类似的操作。或者,您可以将RequestFactoryServlet 子类化并覆盖其doPost() 方法,以在super.doPost() 返回时拆除finally 块中的EntityManager

    【讨论】:

    • 谢谢(再次),BobV。我正在尝试 servlet 过滤器方法。让每个请求一个实体管理器工作,这当然解决了我的 RequestFactory 问题。但现在我正在泄漏资源。它总是一些东西。 :-) 一旦我解决了错误,我会回来总结。
    【解决方案2】:

    如果您使用的是 Spring,您只需将 OpenEntityManagerInView servlet 过滤器添加到您的 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>
    

    【讨论】:

      【解决方案3】:

      这是我根据GWT Google Group,BobV 的反馈最终得出的结论。

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

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

      但到目前为止,这段代码似乎与RequestFactory 配合得很好。非常欢迎提出改进建议。

      注意:这段经历告诉我,可能值得转向完整的 CDI,而不是尝试实现这样的部分。在这个项目期间,我只是没有时间进行这样的举动。

      【讨论】:

      • 我怀疑您会通过此过滤器收到许多不需要 EntityManager 的请求。这正是我所做的,它对我也很有效!在 appengine 上,事务位不起作用,但在 JDO 中打开和关闭持久性管理器也很有效。
      猜你喜欢
      • 2011-06-25
      • 2011-11-28
      • 2011-10-11
      • 2012-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多