如果我有多个线程,每个使用注入器来获取EntityManager对象,每个使用em对象来选择其他类对象的列表。准备好用于for循环。JAVA:多线程环境中的EntityManager对象
如果线程先完成并调用clear(),是否会影响其他线程?像for循环会有例外吗?
close()怎么样?
如果答案是“它取决于”,我应该看看什么(类定义?方法调用?)和where(java代码?注释?xml?)来了解它是如何依赖的?
我没有写出源码,我只是在没有文档的情况下使用别人的库。
谢谢。
如果我有多个线程,每个使用注入器来获取EntityManager对象,每个使用em对象来选择其他类对象的列表。准备好用于for循环。JAVA:多线程环境中的EntityManager对象
如果线程先完成并调用clear(),是否会影响其他线程?像for循环会有例外吗?
close()怎么样?
如果答案是“它取决于”,我应该看看什么(类定义?方法调用?)和where(java代码?注释?xml?)来了解它是如何依赖的?
我没有写出源码,我只是在没有文档的情况下使用别人的库。
谢谢。
管理EntityManager有两种类型:容器管理和应用程序管理。对于管理的应用程序,获取EntityManager的首选方法是通过EntityManagerFactory。 Java EE的教程中这样说:
容器管理的实体管理
与容器管理的实体 经理,一个EntityManager实例的持久化上下文是 由容器自动传播到所有的应用程序,使用 组件事务API(JTA)事务中的单个Java 中的EntityManager实例。
JTA事务通常涉及跨应用程序组件的调用。 要完成JTA事务,这些组件通常需要访问单个持久性上下文的 。当EntityManager通过 javax.persistence.PersistenceContext注释注入到应用程序组件中时,会发生这种情况。使用当前JTA事务 自动传播持久性 上下文,并且映射到相同持久性的EntityManager引用提供对该事务中的持久性上下文的访问。通过自动传播持久化上下文,应用程序组件不需要将对EntityManager实例的引用传递给对方,以便在单个事务中进行更改。 Java EE容器管理容器管理实体管理器的生命周期。
为了获得一个EntityManager实例,注入实体管理器进入 应用程序组件:
@PersistenceContext EntityManager em;
应用管理的实体管理
随着应用程序管理的实体管理器,在其他 手,持久化上下文不会传播到应用程序 组件,并且EntityManager实例的生命周期由应用程序管理 。当应用程序需要访问 是不与特定的持久性 单元跨越EntityManager实例的JTA事务 传播的持久化上下文
应用管理的实体管理器使用。在这种情况下,每个EntityManager会创建一个新的隔离的持久性上下文。 EntityManager及其关联的持久性 上下文是由应用程序明确创建和销毁的。他们 也用于直接注入时EntityManager实例不能被 完成,因为EntityManager实例不是线程安全的。 EntityManagerFactory实例是线程安全的。
谢谢。所以我得到它有两种类型。那我该如何判断这个库正在使用哪种类型? – user1589188 2013-02-15 04:28:44
阅读图书馆的源代码/请教供应商? – gerrytan 2013-02-15 05:29:38
实体管理器不是线程安全(源Java EE 6 tutorial)并且不能被线程之间共享。每个线程都需要使用自己的实体管理器,否则会发生不好的事情,无论是调用clear()
还是close()
。
但是,如果注入器正在使用其自己的实体管理器注入每个线程,那么事情应该是确定的。
Spring和其他可能的DI框架将注入一个真正的实体管理器的基于ThreadLocal的代理到你的bean中。每个线程所做的调用将代理实体管理器的真实线程本地实例 - 即使可能出现实体管理器在多个线程之间共享的情况,情况也是如此。
更多关于你的实体管理器是如何注入将有助于细节(弹簧等)
谢谢!我很乐意协助您的帮助。如果那是相关的,我在图书馆里发现了一些guice。否则,请告诉我如何找到你想知道的东西。 – user1589188 2013-02-15 04:28:01
“每个线程都需要使用自己的实体管理器,否则会发生不好的事情。”可能会出现什么问题,请您详细说明。 – eatSleepCode 2015-09-02 12:03:52
通常你有你的周围使用数据库对象做什么交易。每个给定线程看到的有关其他线程所做更改的内容都由“事务隔离”设置控制。
开始学习不同的隔离设置并根据您的需要应用正确的设置。精度和速度之间有一个折衷。 http://en.wikipedia.org/wiki/Isolation_%28database_systems%29
这是完整的工作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<EntityManager> threadLocal;
static {
emf = Persistence.createEntityManagerFactory("Persistent_Name");
threadLocal = new ThreadLocal<EntityManager>();
}
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();
}
}
关于如何在多线程应用程序中使用这个助手的一个简单例子会很棒。 :) – 2017-10-24 13:43:46
我关通过三年左右的时间:),但就在EJB中注入的EntityManager而言,这里是从那里到亚当边的博客文章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并发问题。
你可以详细介绍一下你的注入机制,以及EntityManager实例是如何的。例如它是一个Spring应用程序。你使用OpenEntityManagerInViewFilter吗? – Rohit 2013-02-15 04:04:06
是的。同一个EntityManager实例/对象在库中传递,但我没有看到任何公共函数来获取它。所以我使用com.google.inject.Injector来让它的实例在我的函数中使用它。 – user1589188 2013-02-15 04:20:12