簡體   English   中英

注入EntityManager Vs. EntityManagerFactory的

[英]Injecting EntityManager Vs. EntityManagerFactory

一個很長的問題,請耐心等待。

我們將Spring + JPA用於Web應用程序。 我的團隊正在討論在GenericDAO注入EntityManagerFactory (在APPFUSE提供的基於泛型的DAO,我們不會出於某種原因使用JpaDaosupport )而不是注入EntityManager 我們正在使用“應用程序管理持久性”。

反對注入EntityManagerFactory的論點是它太重而且不需要, EntityManager做我們需要的。 此外,由於Spring會為每個Web請求創建一個新的DAO實例(我懷疑這一點),因此不會出現任何並發問題,因為同一個EntityManager實例由兩個線程共享。

注入EFM的理由是,它是一個很好的做法,總是很好地擁有工廠的句柄。

我不確定哪種方法最好,有人可以賜教嗎?

優點和注入的EntityManagerFactory VS的EntityManager的缺點在Spring文檔都列明在這里 ,我不知道如果我能在改善。

這么說,你的問題中有一些要點應該被清除。

... Spring將為每個Web請求創建一個新的DAO實例...

這是不正確的。 如果您的DAO是一個Spring bean,那么它是一個單例,除非您通過bean定義中的scope屬性進行配置。 為每個請求實例化DAO都會很瘋狂。

注入EMF的論點是,對於工廠來說,它是一個很好的做法。

這種說法並不真正有用。 一般的良好實踐表明,應該向一個對象注入完成其工作所需的最少合作者。

我正在放下我最終收集到的東西。 從Spring Reference中的“ 基於普通JPA實現DAO ”一節:

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

這意味着根據JPA規范,EntityManager實例不是線程安全的,但如果Spring處理它們,它們將成為線程安全的。

如果您使用的是Spring,最好注入EntityManagers而不是EntityManagerFactory。

我認為這已經很好地涵蓋了,但只是為了強調幾點。

  • 如果由Spring注入,DAO 默認為單例 您必須將范圍顯式設置為prototype,以便每次都創建一個新實例。

  • 由@PersistenceContext注入的實體管理器是線程安全的

話雖這么說,我的多線程應用程序中的單例DAO確實存在一些問題。 我最終使DAO成為一個實例bean,並解決了這個問題。 因此,雖然文檔可能會說一件事,但您可能希望徹底測試您的應用程序。

跟進:

我認為我的一部分問題是我正在使用

@PersistenceContext(unitName = "unit",
    type = PersistenceContextType.EXTENDED)

如果您使用PersistenceContextType.EXTENDED,請記住,如果我理解正確,您必須手動關閉事務。 有關更多信息,請參閱主題。

另一個后續行動:

使用實例化DAO是一個非常糟糕的主意。 DAO的每個實例都有自己的持久性緩存,其他DAO bean無法識別對一個緩存的更改。 抱歉,不好的建議。

我發現在我們的DAO上設置@Repository Spring注釋並使用Spring管理的EntityManager並通過@PersistenceContext注釋注入是使一切工作流暢的最方便的方法。 您可以從共享EntityManager的線程安全性和異常轉換中受益。 默認情況下,如果您將來自管理器的多個DAO組合在一起,則共享的EntityManager將管理事務。 最后你會發現你的DAO會變得貧血。

暫無
暫無

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

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