2010-03-08 3 views
6

У нас есть некоторый компонент JavaEE5 без состояния EJB, который передает введенный EntityManager своим помощникам.Можно ли передать инъецированные EntityManager в классы помощника EJB bean и использовать его?

Безопасно ли это? Он работал хорошо до сих пор, но я узнал какой-то документ Oracle, в котором говорится, что его реализация EntityManager является потокобезопасной. Теперь я задаюсь вопросом, была ли причина, по которой у нас не было проблем до сих пор, было только потому, что используемая нами реализация оказалась потокобезопасной (мы используем Oracle).

@Stateless 
class SomeBean { 
    @PersistenceContext 
    private EntityManager em; 

    private SomeHelper helper; 

    @PostConstruct 
    public void init(){ 
     helper = new SomeHelper(em); 
    } 

    @Override 
    public void business(){ 
     helper.doSomethingWithEm(); 
    } 

} 

На самом деле это имеет смысл .. Если EntityManager является поточно-небезопасным, контейнер должен сделать

inercept business() 
this.em = newEntityManager(); 
business(); 

, который не будет распространяться на его помощник.

Если да, то в чем заключается лучшая практика в подобной ситуации? Передача EntityManagerFactory вместо EntityManager?

EDIT: This question очень интересно, так что если вы заинтересованы в этом вопросе, вы, вероятно, хотите, чтобы проверить это одно, тоже:

EDIT: Больше информации. ejb3.0 spec

4.7.11 неповторно Экземпляры Контейнер должен гарантировать, что только один поток может быть выполнение экземпляра в любое время. Если запрос клиента прибывает для экземпляра, тогда как экземпляр выполняет другой запрос, контейнер может выдать javax.ejb.ConcurrentAccessException на второй клиент [24]. Если используется вид клиента EJB 2.1 , контейнер может бросить java.rmi.RemoteException к второму запросу, если клиент является удаленным клиентом, или javax.ejb.EJBException, если клиент является локальным клиент. [25] Обратите внимание, что объект сеанса предназначен для поддержки только одного клиента. Следовательно, он будет ошибкой приложения, если два клиента попытались вызвать тот же объект сеанса . Одно из значений это правило заключается в том, что приложение не может совершать вызовы с обратным вызовом для экземпляра сеанса .

И

4.3.2 Dependency Injection Сеанс боб может использовать зависимость инъекций механизмов для получения ссылок на ресурсов и других объектов в среде (смотрите главу 16, «Enterprise Bean Environment»). Если сессионного компонент использует зависимость инъекции, контейнер вводит эти ссылок после экземпляра компоненты является создан, и до любого бизнеса методов вызываются на бобе экземпляра.Если объявлена ​​зависимость от SessionContext или если класс bean-класса реализует необязательный интерфейс SessionBean (см. Раздел 4.3.5), SessionContext также вводится в это время. Если зависимость не выполняется, экземпляр компонента отбрасывается. В соответствии с API EJB 3.0 класс bean-класса может получить интерфейс SessionContext через инъекцию зависимостей без использования реализации интерфейса SessionBean. В этом случае аннотация ресурса (или ресурса-env-ref развертывания ) используется для обозначения зависимости компонента от 0CSSessionContext. См. Главу 16, «Экологическая среда предприятия».

+0

Теперь это интересно. «EJB 3.1 Spec говорит, что инъекция зависимостей выполняется только во время построения, так что все вызывающие абоненты MyRepository будут использовать один и тот же экземпляр EntityManager». : http: //stackoverflow.com/questions/2015184/how-is-threadsafty-guranteed-with-persistencecontext –

+0

FYI, читайте также § 4.1.13 или смотрите этот ответ http: // stackoverflow.ком/вопросы/1954137/как-это-что-экземпляр-пулы-с-EJBs-может-улучшить производительность/1954229 # 1954229. Таким образом, каждый помощник будет доступен по одному потоку за раз. – ewernli

+0

Это именно то, что я думал о внедрении. Я очень рад видеть, что это возможно. Отличный пост. Благодарю. – b3bop

ответ

2

Я использовал аналогичный шаблон, но помощник был создан в @PostConstruct, а введенный администратор сущности был передан в конструкторе в качестве параметра. Каждый экземпляр EJB имел свой собственный помощник и безопасность потоков.

У меня также был вариант, если менеджер объекта не был введен (потому что EJB не использовал его вообще), поэтому помощник должен искать его с помощью InitialContext. В этом случае, контекст Постоянство должен еще быть «импортирован» в родительском EJB с @PersistenceContext:

@Stateless 
@PersistenceContext(name="OrderEM") 
public class MySessionBean implements MyInterface { 
    @Resource SessionContext ctx; 
    public void doSomething() { 
    EntityManager em = (EntityManager)ctx.lookup("OrderEM"); 
    ... 
    } 
} 

Но это на самом деле проще вводить его (даже если EJB не использует его), чем искать его , особенно для проверки.

Но, чтобы вернуться к вашему основному вопросу, я думаю, что диспетчер объектов, который вводится или просматривается, является оболочкой, которая пересылается в основной менеджер активного объекта, привязанный к транзакции.

Надеюсь, это поможет.

EDIT

Раздел § 3.3 и § 5.6 в спецификации рассмотрим немного тему.

+0

Спасибо, я рад слышать, что нам не нужно копать наш производственный код! –

2

Я использую Helper методу и прошел EntityManager там, и это совершенно нормально.

Поэтому я бы рекомендовал либо передавать его методам, когда это было необходимо, либо сделать хелпер-компонент сам, ввести его (используя @EJB) и ввести туда EntityManager.

+0

Вспомогательные методы звучат очень просто и хорошо. Благодаря! –

0

Ну, лично я бы не хотел, чтобы мне приходилось передавать Менеджер сущности всем моим POJO в моих конструкторах или методах. Особенно для нетривиальных программ, где количество POJO велико.

Я бы попытался создать POJO/HelperClasses, которые имеют дело с Entities, возвращаемыми EntityManager, вместо непосредственного использования entitymanager.

Если это невозможно, я думаю, что создаю новый EJB Bean.

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

  • Нет связанных вопросов^_^