EJBException при вызове entityManager.getTransaction () - PullRequest
8 голосов
/ 23 июня 2011

Это, вероятно, что-то тривиальное, но я бы хотел помочь.

Я получаю:

 javax.ejb.EJBException: java.lang.IllegalStateException: Illegal to call this method from injected, managed EntityManager 
 11:54:37,105 ERROR [STDERR] at org.jboss.ejb3.tx.Ejb3TxPolicy.handleExceptionInOurTx(Ejb3TxPolicy.java:77)
 11:54:37,105 ERROR [STDERR] at org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:83)
 11:54:37,105 ERROR [STDERR] at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:190)

при выполнении:

@PersistenceContext(unitName = "someName")
private EntityManager em;

...

final EntityManager entityManager = getEntityManager();
final EntityTransaction tx = entityManager.getTransaction(); // here

Может кто-нибудь сказатьмне, что может быть причиной?

Ответы [ 2 ]

19 голосов
/ 23 июня 2011

Недопустимо получать ссылку на экземпляр EntityTransaction, связанный с EntityManager в управляемом контексте Java EE.Из документации API Java EE EntityManager.getTransaction () :

Возвращает объект EntityTransaction уровня ресурсов.Экземпляр EntityTransaction может использоваться последовательно для начала и фиксации нескольких транзакций.

Returns:
    EntityTransaction instance 
Throws:
    IllegalStateException - if invoked on a JTA entity manager

Последняя строка уместна в этом контексте.

Когда вы внедряете EntityManager в развернутый EJB-компонентна сервере приложений, использующем аннотации @PersistenceContext или @Inject, EntityManager будет управляться контейнером, а не приложением.Контроллером управляемого объекта контейнера должен быть JTA Entity Manager;Менеджеры сущностей, управляемые приложением, могут быть локальными менеджерами сущностей.Это продиктовано спецификацией JPA:

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

Менеджер объекта, базовые транзакции которого контролируютсяприложение через API-интерфейс EntityTransaction называется локально-ресурсным менеджером сущностей.

Диспетчер сущностей, управляемый контейнером, должен быть диспетчером сущностей JTA. Менеджеры сущностей JTA определены только для использования в Java EEконтейнеры.

Начиная с первого пункта (касательно исключения IllegalStateException), вы не должны получать ссылку EntityTransaction для внедренных контейнеров EntityManager.Однако вы можете сделать это, если контейнер внедрил только EntityManagerFactory, и ваше приложение получило ссылку EntityManager, вызвав EntityManagerFactory.getEntityManager.

Кроме того, следует отметить, что вызов EntityManager.getTransaction() не имеет смысла для менеджеров сущностей JTA,На это указывает спецификация JPA в определении интерфейса EntityTransaction:

Интерфейс EntityTransaction используется для управления транзакциями ресурсов в менеджерах локальных ресурсов ресурса.

Что касается управления самой транзакцией JTA, если вам нужно самостоятельно управлять границами транзакции (т. Е. Использовать транзакции, управляемые компонентом), введите экземпляр UserTransaction.Или, если вы хотите, чтобы контейнер управлял транзакцией, просто аннотируйте метод или компонент с соответствующим значением TransactionalAttribute .

Как правило, не рекомендуется использовать локальные для ресурсов менеджеры объектов (и источники данных) с управляемыми компонентом или контейнером управляемыми транзакциями на сервере приложений, но это можно сделать.

Youнайдет подходящий пример, демонстрирующий использование BMT с внедрением EntityManager в документацию Hibernate EntityManager .CMT еще более тривиальны, если вы уже аннотировали свои классы или методы bean-компонентов;вам просто нужно избегать вызова метода getEntityTransaction() для работы CMT.

Если вы хотите понять дальше, я бы рекомендовал прочитать главу 7 спецификации JPA 2.0 под названием «Entity Managers and Persistence Contexts»,Примеры, приведенные в этой главе, демонстрируют:

  • как менеджеры сущностей JTA должны использоваться на сервере приложений (обычно это место, где они используются).
  • как ресурс-локальные менеджеры сущностей могут использоваться на сервере приложений.
  • , как локально-ресурсные менеджеры сущностей могут использоваться в приложении Java SE.
3 голосов
/ 23 июня 2011

Вам не нужно создавать экземпляр EntityManager вручную, ваш контейнер делает это за вас из-за аннотации @PersistenceContext.Кроме того, вам не нужно начинать транзакцию вручную, она также предоставляется вашим контейнером.Просто используйте поле em и забудьте о других.

...