簡體   English   中英

JPA交易如何運作

[英]How JPA transactions works

每當我想要持久化任何實體時,都會執行以下代碼。 事情似乎工作正常,但我不明白它是如何工作的!

EntityManager em = getEntityManager();
EntityTransaction userTransaction = em.getTransaction();
userTransaction.begin();
em.persist( ent );
userTransaction.commit();

上面的EntityManager是整個應用程序共享的單個實例。 開始交易后; 我只是說em.persist(實體).. hibernate如何知道它屬於哪個事務!

假設我的應用程序上有10個並發用戶,並且所有10個線程都在代碼上執行。 因此,創建並提交了10個獨立事務。 但所有10個不同的實體我並沒有將它們與各自的交易聯系起來; 那么JPA如何能夠解決這個問題呢!

根據答案; 我們在下面; 我們是說每個線程應該有一個EntityManager實例嗎? 這不會是服務器上的殺戮! 我們應該匯集這些實例嗎? 是不是等於再次實現一種連接池?

它使用ThreadLocal變量進行Transaction。

另請參閱UserTransaction的文檔:

開始()
創建一個新事務並將其與當前線程關聯。

您不應該共享EntityManager,因為它不保證是線程安全的。

但是,如果您在EJB中注入它,則不必擔心線程安全: http//www.adam-bien.com/roller/abien/entry/is_in_an_ejb_injected

如果您使用Spring注入它,您將獲得一個線程安全的代理: http//static.springsource.org/spring/docs/3.1.1.RELEASE/spring-framework-reference/html/orm.html #ORM,JPA直

雖然EntityManagerFactory實例是線程安全的,但EntityManager實例不是。 注入的JPA EntityManager的行為類似於從應用程序服務器的JNDI環境獲取的EntityManager,如JPA規范所定義。 它將所有調用委托給當前的事務性EntityManager,如果有的話; 否則,它會回退到每個操作新創建的EntityManager,實際上使其使用線程安全。

這很有效,因為你很幸運。 幸運的是,意味着以正確的順序調用commit和begin。

您確實使用來自多個線程的實體管理器的單個實例。 這是不對的,因為它不能保證是線程安全的。 通過EntityTransaction訪問資源級別事務綁定到實體管理器實例,而不是線程。

因此,結果是您正在共享相同的EntityTransaction並幸運地連續使用它進行多個事務。 使用它來串行和結束多個事務很好,但是從許多線程使用它不是。

在hibernate(4.1.4)中,引用存儲在AbstractEntityManageImpl類的tx實例字段中,但這只是實現細節。

事務使用ThreadLocal變量以某種方式與當前線程相關聯。

我建議您了解JTA如何工作而不管Hibernate - 這對您的理解非常重要
另外,閱讀有關容器管理的事務和bean管理的事務。
如果您正在使用容器管理的事務,則可以為您注入EntityManager的bean指定什么是事務范圍 -
例如 - 如果范圍是REQUIRED,則意味着如果另一個bean調用此bean,而不是在事務的上下文中,則將打開一個新事務。 如果事務已存在,那么您將使用相同的事務。 了解這一點非常重要,因為事務是系統中的一種昂貴資源。

事務對象與ThreadLocal相關聯,但是,另一個線程可能會恢復掛起的事務,這取決於您的TransactionManager的實現(我在談論JBossTransactionManager

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM