Недопустимо получать ссылку на экземпляр 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.