如果我有多個線程,每個使用注入器來獲取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