2012-08-26 36 views
1

我正在使用Java SE 7的桌面應用程序工作。應用程序使用多線程,並且在創建的每個線程中注入DAO類以獲取對我的數據庫的訪問權限。作爲持久層我使用EclipseLink和JPA。 EntityManager的注入採用構造器注入我的DAO類,因爲它不是線程安全的,我去使用Provder這樣的辦法:Guice在多線程應用程序中注入EntityManager

public PluginInstanceJpaController implements IPluginInstanceDao { 

    private EntityManager em; 

    @Injected 
    public PluginInstanceJpaController(Provider<EntityManager> emp) { 
     this.em = emp.get(); 
    } 

    @Transactional 
    public void create(PluginInstance foo) throws Exception { 
     em.persist(foo); 
    } 
} 

然而,同樣的EntityManager實例注入每個DAO。爲了設置它,我使用了JpaPersistModule,因爲它是由guice提供的,我確信到目前爲止我的設置中沒有單例。

有沒有人知道如何告訴guice在注入時創建一個EntityManager的新實例?

在另一種方法中,我嘗試了EntityManagerFactory和EntityManager的自定義提供程序,並使JpaPersistModule離開我的業務。這導致每個DAO都有一個EntityManager實例,但是@Transactional註釋的方法沒有被攔截。

我很感謝這個問題的任何解決方案。 到目前爲止感謝!

---編輯---

的DAO類注入到正在使用他們一個Runnable。 Runnable也通過Provider提供。我的模塊配置看起來像這樣:

public class RepositoryModule extends AbstractModule { 

    @Override 
    protected void configure() { 

     // DAO bindings 
     bind(IObjectStoreDao.class).to(ObjectStoreJpaController.class); 
     bind(IPluginInstanceDao.class).to(PluginInstanceJpaController.class); 
    } 

    @Provides 
    public PluginMonitor newMonitor(IPluginInstanceDao plugDao, IObjectStoreDao osDao) { 
     PluginMonitor m = new PluginMonitor(); 
     m.setPluginInstanceDao(plugDao); 
     m.setObjectStoreDao(osDao); 
     return m; 
    } 
} 

這裏PluginMonitor是我的Runnable。注射器本身是在我的主線程中創建的......可能這是問題嗎?

回答

0

我不熟悉的JPA,但我希望我仍然可以幫助:-)

如果你看一下the source for EntityManagerProvider,你可以看到有一個ThreadLocal<EntityManager>。所以默認情況下,每個線程應該有自己的EntityManager。這使我相信這個問題在別處。你確定沒有模塊將EntityManager設置爲單身嗎?你如何確定所有的EntityManager是同一個對象?每個DAO絕對是在自己的線程上?你能否提供關於如何在模塊中配置FooDao的細節以及如何爲每個線程提供新的FooDao?

此外,你應該罰款寫你的構造函數:

@Inject 
public FooDao(EntityManager emp) { 
    this.em = emp; 
} 

吉斯會做的魔力爲你確定EntityManagerProvider提供EntityManager實例,並調用get()EntityManagerProvider實例來得到一個EntityManager給你的構造函數。

+0

嗨!我正在使用eclipse調試器,它爲每個線程中的任何EntityManager引用提供了相同的調試ID,因此如果我將這個引用正確地通知給同一個實例。 DAO是由提供可運行的提供程序(我的實際線程可運行)注入的。經過幾個小時的努力之後,我決定刪除guice,並以我自己的方式。不過也許這個討論可能有助於某人。 – Markus

2

這是非常相似的問題:How Guice injects singletons and non-singletons into multiple threads

要在DAO,這應該工作。

public PluginInstanceJpaController implements IPluginInstanceDao { 

    private Provider<EntityManager> emProvider; 

    @Injected 
    public PluginInstanceJpaController(Provider<EntityManager> emp) { 
     this.em = emp; 
    } 

    @Transactional 
    public void create(PluginInstance foo) throws Exception { 
     em.get().persist(foo); 
    } 
} 

您應該使用Jpa Persistence Module或創建自定義的EntityManager提供商,這將返回新的EntityManager每個get()方法調用,也可以使用ThreadLocal中實施,以確保EntityManager的跨越將線程共享。

相關問題