JAVA:multithreading环境中的EntityManager对象

如果我有多个线程,每个使用注入器来获取EntityManager对象,每个使用em对象来选择其他类对象的列表。 准备用于for循环。

如果一个线程先完成并调用clear(),那会影响其他线程吗? 喜欢for循环会有exception吗?

close()怎么样?

如果答案是“它取决于”,那么(类定义?方法调用?)和where(java code?annotation?xml?)应该看看它是如何依赖的?

我没有写源,我只是在没有文档的情况下使用别人的库。

谢谢。

这是完整的thread-safe Entity Manager Helper

 import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; public class EntityManagerHelper { private static final EntityManagerFactory emf; private static final ThreadLocal threadLocal; static { emf = Persistence.createEntityManagerFactory("Persistent_Name"); threadLocal = new ThreadLocal(); } public static EntityManager getEntityManager() { EntityManager em = threadLocal.get(); if (em == null) { em = emf.createEntityManager(); // set your flush mode here threadLocal.set(em); } return em; } public static void closeEntityManager() { EntityManager em = threadLocal.get(); if (em != null) { em.close(); threadLocal.set(null); } } public static void closeEntityManagerFactory() { emf.close(); } public static void beginTransaction() { getEntityManager().getTransaction().begin(); } public static void rollback() { getEntityManager().getTransaction().rollback(); } public static void commit() { getEntityManager().getTransaction().commit(); } } 

实体管理器不是线程安全的(源Java EE 6教程 ),不能在线程之间共享。 每个线程都需要使用自己的实体管理器,否则会发生不好的事情,无论是clear()还是close()调用。

但是,如果注入器使用自己的实体管理器注入每个线程,那么事情应该没问题。

Spring和可能的其他DI框架会将真实实体管理器的基于ThreadLocal的代理注入到bean中。 每个线程所做的调用将代理实体管理器的真实线程本地实例 – 这就是事情可以工作的方式,即使它可能看起来实体管理器在多个线程之间共享。

有关如何注入实体管理器的更多细节将有所帮助(Spring等)

管理EntityManager有两种类型:容器管理和应用程序管理。 对于托管应用程序,获取EntityManager的首选方法是通过EntityManagerFactory。 Java EE教程说:

容器管理的实体经理

使用容器管理的实体管理器,容器会自动将EntityManager实例的持久性上下文传播到在单个Java Transaction API(JTA)事务中使用EntityManager实例的所有应用程序组件。

JTA事务通常涉及跨应用程序组件的调用。 要完成JTA事务,这些组件通常需要访问单个持久性上下文。 当通过javax.persistence.PersistenceContext批注将EntityManager注入应用程序组件时,会发生这种情况。 使用当前JTA事务自动传播持久性上下文,并且映射到同一持久性单元的EntityManager引用提供对该事务中的持久性上下文的访问。 通过自动传播持久性上下文,应用程序组件不需要将对EntityManager实例的引用传递给彼此,以便在单个事务中进行更改。 Java EE容器管理容器管理的实体管理器的生命周期。

要获取EntityManager实例,请将实体管理器注入应用程序组件:

 @PersistenceContext EntityManager em; 

应用程序管理的实体经理

另一方面,使用应用程序管理的实体管理器,持久性上下文不会传播到应用程序组件,并且EntityManager实例的生命周期由应用程序管理。

当应用程序需要访问特定持久性单元中的EntityManager实例中未使用JTA事务传播的持久性上下文时,将使用应用程序管理的实体管理器。 在这种情况下,每个EntityManager都会创建一个新的,独立的持久化上下文。 EntityManager及其关联的持久性上下文由应用程序显式创建和销毁。 直接注入EntityManager实例时也会使用它们,因为EntityManager实例不是线程安全的。 EntityManagerFactory实例是线程安全的。

http://docs.oracle.com/javaee/6/tutorial/doc/bnbqw.html

您通常会处理有关数据库对象的事务。 每个给定线程看到的其他线程所做的更改由“事务隔离”设置控制。

开始了解不同的隔离设置,并根据您的需要应用正确的设置。 在准确性和速度之间进行权衡。 http://en.wikipedia.org/wiki/Isolation_%28database_systems%29

我离开了三年左右:),但就EJB中注入EntityManager而言,这里是Adam Bien博客文章的链接http://www.adam-bien.com/roller/abien/entry/is_in_an_ejb_injected

从那里复制粘贴:

“你可以将EntityManager直接注入到EJB中。但是:它是否是线程安全的?:

 @Stateless public class BookServiceBean implements BookService { @PersistenceContext EntityManager em; public void create(Book book) { this.em.persist(book);} } 

答案是,再次复制粘贴:

“无论是同时调用一个方法还是多个方法,无需进一步配置即可使用EJB是线程安全的。容器关心调用的序列化。”,

这可能更清楚,但它暗示您可以在无状态会话bean中注入EntityManager,而不必担心EntityManager并发问题。