2011-08-30 145 views
0

我一直在使用JPA 2.0實現EclipseLink 2.2.0開發我的web應用程序。我終於可以運行多線程代碼,我得到這個異常:關於多線程和EntityManager的問題

java.lang.IllegalStateException: Attempting to execute an operation on a closed EntityManager. 

有我的應用程序中的所有javax.persistence呼叫被定義爲應用程序作用域的對象,像這樣:

@Model 
@ApplicationScoped 
public class LocationControl implements Serializable { 

    @PersistenceContext private EntityManager em; 
    @Resource   private UserTransaction utx; 

    // etc 

,當然一切要訪問的數據庫的管理Bean(一般RequestScoped或ConversationScoped)這樣做是這樣的:

@Inject private LocationControl lc; 

所以我的問題是這樣的:我一步步該異常通過使用@ApplicationScoped DAO?我以爲這樣做會更有效率,因爲如果沒有範圍,容器就不必在每個請求上不斷重新創建這個對象,並且DAO沒有自己的狀態。但是,如果EntityManager和UserTransaction對象必須是每個用戶的獨立實例,那麼這將是一個問題。

或者,我可以在DAO方法上使用syncrhonized,但我認爲這會導致容器中的線程鎖定(GlassFish)。

任何意見讚賞。

+0

我沒有做CDI,但'LocationControl'通常應該是一個'@ Stateless' EJB,並且要被'@ EJB'注入。我不知道'@ Model'代表什麼,但是這對商業服務類來說是錯誤的。 – BalusC

回答

1

@Model註釋最初創建註釋請求範圍豆,這裏是它是如何定義的:

@Named 

@RequestScoped 

@Stereotype 

@Target({TYPE, METHOD, FIELD}) 

@Retention(RUNTIME) 

public @interface Model {} 

當然你也可以重寫「@RequestScoped」與另一個註解,但是「@ApplicationScoped」它不是一個好因爲應用程序中的每個人都會修改相同注入的EntityManager的狀態。我認爲在大多數情況下最好放棄@RequestScoped,有時候,例如登錄/註銷數據bean'@SessionScoped'可能是一個選項,但我看不到'@ApplicationScoped'dao的場景。

如果您根本不想使用@Model並且使用完整的Java EE容器,那麼無狀態的EJB,就像BalusC所說的那樣,對Dao來說也是一個很好的選擇。

+0

我認爲我們在這裏對'@Model'的用法有偏見。實際上它是'@Named'的擴展,我將我的代碼轉換爲使用'@Named'。但真正的問題是,我是否可以使用單個DAO實例來引用具有多個線程的單個EntityManager和UserTransaction。 – AlanObject

+0

即使您使用'@Named'而不是'@Model',仍然使用'@ApplicationScope',您將使您的實體管理器成爲全局的,並且我認爲它不應該是。 – Kris

+0

好吧,我想我將不得不這樣做。感謝您的輸入。 – AlanObject