2013-02-15 180 views
21

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

如果线程先完成并调用clear(),是否会影响其他线程?像for循环会有例外吗?

close()怎么样?

如果答案是“它取决于”,我应该看看什么(类定义?方法调用?)和where(java代码?注释?xml?)来了解它是如何依赖的?

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

谢谢。

+0

你可以详细介绍一下你的注入机制,以及EntityManager实例是如何的。例如它是一个Spring应用程序。你使用OpenEntityManagerInViewFilter吗? – Rohit 2013-02-15 04:04:06

+0

是的。同一个EntityManager实例/对象在库中传递,但我没有看到任何公共函数来获取它。所以我使用com.google.inject.Injector来让它的实例在我的函数中使用它。 – user1589188 2013-02-15 04:20:12

回答

4

管理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实例是线程安全的。

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

+0

谢谢。所以我得到它有两种类型。那我该如何判断这个库正在使用哪种类型? – user1589188 2013-02-15 04:28:44

+0

阅读图书馆的源代码/请教供应商? – gerrytan 2013-02-15 05:29:38

9

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

但是,如果注入器正在使用其自己的实体管理器注入每个线程,那么事情应该是确定的。

Spring和其他可能的DI框架将注入一个真正的实体管理器的基于ThreadLocal的代理到你的bean中。每个线程所做的调用将代理实体管理器的真实线程本地实例 - 即使可能出现实体管理器在多个线程之间共享的情况,情况也是如此。

更多关于你的实体管理器是如何注入将有助于细节(弹簧等)

+0

谢谢!我很乐意协助您的帮助。如果那是相关的,我在图书馆里发现了一些guice。否则,请告诉我如何找到你想知道的东西。 – user1589188 2013-02-15 04:28:01

+1

“每个线程都需要使用自己的实体管理器,否则会发生不好的事情。”可能会出现什么问题,请您详细说明。 – eatSleepCode 2015-09-02 12:03:52

1

通常你有你的周围使用数据库对象做什么交易。每个给定线程看到的有关其他线程所做更改的内容都由“事务隔离”设置控制。

开始学习不同的隔离设置并根据您的需要应用正确的设置。精度和速度之间有一个折衷。 http://en.wikipedia.org/wiki/Isolation_%28database_systems%29

27

这是完整的工作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(); 
    } 
} 
+0

关于如何在多线程应用程序中使用这个助手的一个简单例子会很棒。 :) – 2017-10-24 13:43:46

0

我关通过三年左右的时间:),但就在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并发问题。