令我大吃一惊的是(在春季使用jpa多年之后)不是线程安全的。如果你更深入地考虑它,这实际上是可以理解的:它只是一个围绕本机JPA实现的包装器,例如Hibernate中的会话,而Hibernate又是围绕jdbc连接的包装器。话虽如此,这不可能是线程安全的,因为它表示一个数据库连接/事务。EntityManager
EntityManager
EntityManager
那么为什么它在春天有效呢?因为它将目标包装在代理中,原则上用于保持每个线程的本地引用。这是必需的,因为Spring应用程序建立在单例之上,而EJB使用对象池。EntityManager
ThreadLocal
在你的情况下,你怎么能处理这个问题呢?我不知道cdi,但在EJB中,每个无状态和有状态会话bean都是池化的,这意味着你不能同时从多个线程调用同一个EJB的方法。因此,从不同时使用。话虽如此,注入EntityManager
是安全的,至少注入无状态和有状态会话bean。EntityManager
然而,将EntityManager
注入servlet和单例bean是不安全的,因为可能多个线程可以同时访问它们,从而弄乱了相同的JDBC连接。
另请参见
尽管 EntityManager 实现本身不是线程安全的,但 Java EE 容器会注入一个代理,该代理将所有方法调用委托给事务绑定的 EntityManager。因此,每个事务都使用自己的 EntityManager 实例。这至少适用于事务范围的持久性上下文(这是默认值)。
如果容器在每个bean中注入一个新的EntityManager实例,则以下操作将不起作用:
@Stateless
public class Repository1 {
@EJB
private Repository2 rep2;
@PersistenceContext(unitName="blah", type = PersistenceContextType.TRANSACTION)
private EntityManager em;
@TransactionAttribute
public void doSomething() {
// Do something with em
rep2.doSomethingAgainInTheSameTransaction();
}
}
@Stateless
public class Repository2 {
@PersistenceContext(unitName="blah", type = PersistenceContextType.TRANSACTION)
private EntityManager em;
@TransactionAttribute
public void doSomethingAgainInTheSameTransaction() {
// Do something with em
}
}
doSomething->doSomethingAgainTheSameTransaction 调用发生在单个事务中,因此 Bean 必须共享相同的 EntityManager。实际上,它们共享相同的代理 EntityManager,该代理将调用委托给相同的持久性上下文。
因此,您是合法使用 EntityManager 在单例 bean 中,如下所示:
@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.BEAN)
public class Repository {
@PersistenceContext(unitName="blah", type = PersistenceContextType.TRANSACTION)
private EntityManager em;
}
另一个证据是,在EntityManager javadoc中没有提到线程安全。因此,当您留在 Java EE 容器中时,您不应该关心对 EntityManager 的并发访问。
-
如何使用Java中的RESTful Web服务获取远程/客户端IP地址? 我已经在我的项目中编写了Rest Web服务。Web服务调用可能来自不同 machine.so 我需要通过REST Web服务找出IP地址。 从这个请求.getRemoteAddr()使用这个。 但是我不能使用getRemoteAddr()。因为我的请
-
从包含大量文件的zip文件中提取1文件的最快方法是什么? 我尝试了但它们也缺少一些东西。 LZMA SDK不提供一种如何使用的文档/教程,这非常令人沮丧。没有 javadoc。 虽然7z jbinding没有提供一种简单的方法来只提取1个文件,但是,它只提供了提取zip文件
-
输入/输出流在销毁时是否关闭? Java 中的 InputStreams 和 OutputStreams 是否在销毁时关闭()?我完全理解这可能是不好的形式(特别是在C和C++世界中),但我很好奇。 另外,假设我有以下代码: 无名的FileInputStream是否在p.load
-
Java 程序中的字符串大小是否有任何限制? 我有一个字符串定义为 字符串 xx 我可以分配的字符数是否有任何限制? 2) 我正在将用户输入分配给此字符串 xx。70%的人只说一个字。有时他们给出一个大句子,所以想知道可
-