2012-08-26 2 views
1

Я работаю над настольным приложением с использованием Java SE 7. В приложении используется несколько потоков, и в каждом потоке, который создается, DAO-класс вводится для получения доступа к моей базе данных. В качестве слоя persistence я использую 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, и я уверен, что в моей настройке пока нет синглтонов.

Кто-нибудь знает, как сообщить о появлении нового экземпляра EntityManager при инъекции?

В другом подходе я пробовал настраиваемые поставщики для EntityManagerFactory и EntityManager и оставил JpaPersistModule вне моего бизнеса. Это привело к экземпляру EntityManager для DAO, однако @Transactional аннотированные методы не были перехвачены.

Буду признателен за решение этой проблемы. Спасибо!

--- --- РЕДАКТИРОВАТЬ

дао классы вводят в Runnable, который их использованием. Runnable также предоставляется через Поставщика. Конфигурация моего модуля выглядит примерно так:

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 s - это один и тот же объект? Каждый DAO определенно находится в своей собственной теме? Можете ли вы предоставить подробную информацию о том, как FooDao настроен в вашем модуле и как новый FooDao предоставляется для каждого потока?

Кроме того, вы должны быть хорошо, чтобы написать конструктор, как:

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

Guice будет делать чудеса для вас определения того, что EntityManagerProvider обеспечивает EntityManager экземпляров, и будет вызывать get() на экземпляре EntityManagerProvider получить EntityManager чтобы дать вашему конструктору.

+0

Hi!Я использовал отладчик eclipse, который дал мне тот же идентификатор отладки на любой ссылке EntityManager в каждом потоке, поэтому, если я правильно проинформирован, это ссылки на один и тот же экземпляр. DAO вводятся Поставщиком, который предоставляет runnable (мой фактический Runnable Thread). После того, как я боролся с этим в течение нескольких часов, я решил удалить губы и пойти своим путем. Однако, возможно, это обсуждение может помочь кому-то. – 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 для каждого вызова получить(), также он может быть реализован с ThreadLocal для обеспечения EntityManager будет распределена по всей теме.

Смежные вопросы