调用entityManager.getTransaction()时出现EJBException
这可能是一件微不足道的事情,但我希望得到一些帮助。
我得到:
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
谁能告诉我原因可能是什么?
This is probably something trivial, but I'd love some help.
I get:
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)
when doing:
@PersistenceContext(unitName = "someName")
private EntityManager em;
...
final EntityManager entityManager = getEntityManager();
final EntityTransaction tx = entityManager.getTransaction(); // here
Can anyone tell me what the cause might be ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在 Java EE 托管上下文中获取与 EntityManager 关联的 EntityTransaction 实例的引用是非法的。来自 EntityManager.getTransaction():
最后一行与此上下文相关。
当您使用 @PersistenceContext 或 @Inject 注释将 EntityManager 注入部署在应用程序服务器上的 EJB 中时,EntityManager 将由容器而不是应用程序管理。容器管理的实体管理器必须是 JTA 实体管理器;应用程序管理的实体管理器可以是资源本地实体管理器。这是由 JPA 规范规定的:
从第一点(关于 IllegalStateException)推断,您不得获取容器注入的 EntityManager 的 EntityTransaction 引用。但是,如果容器仅注入 EntityManagerFactory,并且您的应用程序通过调用 EntityManagerFactory.getEntityManager 获取了 EntityManager 引用,则您可以这样做。
另外,应该注意的是,调用
EntityManager.getTransaction()
对于JTA实体管理器来说是没有意义的。 JPA 规范在 EntityTransaction 接口的定义中指出了这一点:关于管理 JTA 事务本身的主题,如果您需要自己管理事务边界(即使用 bean 管理的事务),请注入
UserTransaction
实例。或者,如果您希望让容器管理事务,则只需使用适当的 TransactionalAttribute 值。在应用程序服务器中将资源本地实体管理器(和数据源)与 bean 管理或容器管理事务一起使用通常不是一个好主意,但这是可以做到的。
您将在 Hibernate EntityManager 文档。如果您已经注释了您的 bean 类或方法,那么 CMT 就更简单了;您只需避免调用
getEntityTransaction()
方法即可让 CMT 正常工作。如果您想进一步了解,我建议您阅读 JPA 2.0 规范的第 7 章,标题为“Entity Managers and Persistence Contexts”。本章提供的示例演示:
It is illegal to obtain a reference to the EntityTransaction instance associated with the EntityManager in a Java EE managed context. From the Java EE API documentation of EntityManager.getTransaction():
The last line is pertinent in this context.
When you inject the EntityManager in an EJB deployed on an application server using the @PersistenceContext or @Inject annotations, the EntityManager will be managed by the container and not by the application. A container managed entity manager must be a JTA Entity Manager; application-managed entity managers can be resource-local entity managers. This is dictated by the JPA specification:
Inferring from the first point (regarding the IllegalStateException), you must not obtain the EntityTransaction reference for container injected EntityManagers. You may however do so, if the container injected only the EntityManagerFactory, and your application obtained the EntityManager reference by invoking
EntityManagerFactory.getEntityManager
.Additionally, it should be noted that invoking
EntityManager.getTransaction()
is meaningless for JTA entity managers. This is indicated by the JPA specification, in the definition of the EntityTransaction interface:On the topic of managing the JTA transaction itself, if you need to manage the transaction boundaries yourself (i.e. use bean-managed transactions), inject the
UserTransaction
instance. Or if you wish to have the container manage the transaction, then simply annotate the method or the bean, with the appropriate TransactionalAttribute value.It is usually not a good idea to use resource-local entity managers (and data sources) with bean managed or container managed transactions in an application server, but it can be done.
You will find a suitable example demonstrating the use of BMTs with injection of the EntityManager in the Hibernate EntityManager documentation. CMTs are even more trivial if you've already annotated your bean classes or methods; you merely have to avoid invoking the the
getEntityTransaction()
method for CMTs to work.If you wish to understand further, I would recommend reading Chapter 7 of the JPA 2.0 specification, titled "Entity Managers and Persistence Contexts". The examples provided in the chapter demonstrate:
您不需要手动实例化 EntityManager,您的容器会为您执行此操作,因为
@PersistenceContext
注释。此外,您不需要手动开始事务,它也是由您的容器提供的。只需使用您的em
字段即可,而无需考虑其他字段。You don't need to instantiate the
EntityManager
by hand, your container does that for you because of the@PersistenceContext
annotation. Also, you don't need to begin the transaction manually, it's also provided by your containter. Just use yourem
field and forget about the other ones.