基於來自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網址模式:
<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爲每個請求創建通過此servlet,無論是使用您的基礎鱈魚是否。它可能會變得更加健壯,並且只是在被請求的時候以某種方式懶惰地創建EntityManager(和事務)。
但到目前爲止,該代碼似乎與RequestFactory
很好。改進建議非常受歡迎。
注意:這個經驗告訴我,它可能值得移到全CDI上,而不是試圖實現這樣的部分。在這個項目中,我只是沒有時間做這樣的動作。
我懷疑你會通過這個過濾器有很多請求不需要EntityManager。這正是我所做的,對我來說也是很好的!在appengine上,事務位不起作用,但是在JDO中打開和關閉持久性管理器也很有效。 – 2011-02-21 20:22:31