2013-02-15 17 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併發問題。