Guice injected EntityManager in multi threaded application

半城伤御伤魂 提交于 2020-01-01 17:25:09

问题


I'm working on a desktop application using Java SE 7. The application uses multiple threads and in each thread that is created a DAO class is injected to gain access to my database. As persistence layer i'm using EclipseLink and JPA. The EntityManager is injected into my DAO class using constructor injection and since it is not thread safe, I went for the approach using a Provder like this:

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);
    }
}

However, the very same EntityManager instance is injected into each DAO. For setting that up I used the JpaPersistModule as it is provided by guice and i'm sure that there are not singletons in my setup so far.

Does anyone know how to tell guice to create a new instance of the EntityManager when injecting?

In another approach I tried custom providers for the EntityManagerFactory and the EntityManager and leaving the JpaPersistModule out of my business. This resulted in a EntityManager instance per DAO, however @Transactional annotated methods were not intercepted then.

I'd appreciate any solution to this issue. Thanks so far!

--- EDIT ---

The DAO classes are injected into a Runnable that is using them. The Runnable is also provided through a Provider. My module configuration looks something like this:

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;
    }
}

Here PluginMonitor is my Runnable. The Injector itself is created in my main thread... might this have been the issue?


回答1:


This is very similiar issue: How Guice injects singletons and non-singletons into multiple threads

To your DAO, this should work.

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);
    }
}

You should use Jpa Persistence Module or create custom EntityManager provider, which will return new EntityManager for each get() call, also it can be implemented with ThreadLocal to ensure EntityManager will be shared across thread.




回答2:


I'm not familiar with JPA, but hopefully I can still help :-)

If you look at the source for EntityManagerProvider, you can see there's a ThreadLocal<EntityManager>. So by default, each thread should have its own EntityManager. That leads me to believe the problem is elsewhere. Are you sure that no module is setting the EntityManager to be a singleton? How are you determining that all the EntityManagers are the same object? Each DAO is definitely on its own thread? Can you provide details on how FooDao is configured in your module and how a new FooDao is provided to each thread?

Also, you should be fine to write your constructor as:

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

Guice will do the magic for you of determining that EntityManagerProvider provides EntityManager instances, and will call get() on the EntityManagerProvider instance to get an EntityManager to give to your constructor.



来源:https://stackoverflow.com/questions/12128552/guice-injected-entitymanager-in-multi-threaded-application

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!