调用entityManager.getTransaction()时出现EJBException

发布于 2024-11-17 01:40:50 字数 764 浏览 2 评论 0原文

这可能是一件微不足道的事情,但我希望得到一些帮助。

我得到:

 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

错々过的事 2024-11-24 01:40:50

在 Java EE 托管上下文中获取与 EntityManager 关联的 EntityTransaction 实例的引用是非法的。来自 EntityManager.getTransaction():

返回资源级EntityTransaction对象。这
可以使用EntityTransaction实例
串行开始并提交多个
交易。

<前><代码>返回:
实体事务实例
投掷:
IllegalStateException - 如果在 JTA 实体管理器上调用

最后一行与此上下文相关。

当您使用 @PersistenceContext 或 @Inject 注释将 EntityManager 注入部署在应用程序服务器上的 EJB 中时,EntityManager 将由容器而不是应用程序管理。容器管理的实体管理器必须是 JTA 实体管理器;应用程序管理的实体管理器可以是资源本地实体管理器。这是由 JPA 规范规定的:

一个实体管理器,其底层
交易是通过控制
JTA被称为JTA实体管理器。

一个实体管理器,其底层
交易由以下机构控制
申请通过
EntityTransaction API 被称为
资源本地实体管理器。

容器管理的实体管理器
必须是 JTA 实体管理员。
JTA
实体管理器仅指定用于
在 Java EE 容器中使用。

从第一点(关于 IllegalStateException)推断,您不得获取容器注入的 EntityManager 的 EntityTransaction 引用。但是,如果容器仅注入 EntityManagerFactory,并且您的应用程序通过调用 EntityManagerFactory.getEntityManager 获取了 EntityManager 引用,则您可以这样做。

另外,应该注意的是,调用EntityManager.getTransaction()对于JTA实体管理器来说是没有意义的。 JPA 规范在 EntityTransaction 接口的定义中指出了这一点:

EntityTransaction 接口用于控制资源本地实体管理器上的资源事务。

关于管理 JTA 事务本身的主题,如果您需要自己管理事务边界(即使用 bean 管理的事务),请注入 UserTransaction 实例。或者,如果您希望让容器管理事务,则只需使用适当的 TransactionalAttribute 值。

在应用程序服务器中将资源本地实体管理器(和数据源)与 bean 管理或容器管理事务一起使用通常不是一个好主意,但这是可以做到的。

您将在 Hibernate EntityManager 文档。如果您已经注释了您的 bean 类或方法,那么 CMT 就更简单了;您只需避免调用 getEntityTransaction() 方法即可让 CMT 正常工作。

如果您想进一步了解,我建议您阅读 JPA 2.0 规范的第 7 章,标题为“Entity Managers and Persistence Contexts”。本章提供的示例演示:

  • 应如何在应用程序服务器(通常是使用它们的地方)中使用 JTA 实体管理器。
  • 如何在应用程序服务器中使用资源本地实体管理器。
  • 如何在 Java SE 应用程序中使用资源本地实体管理器。

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():

Return the resource-level EntityTransaction object. The
EntityTransaction instance may be used
serially to begin and commit multiple
transactions.

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

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:

An entity manager whose underlying
transactions are controlled through
JTA is termed a JTA entity manager.

An entity manager whose underlying
transactions are controlled by the
application through the
EntityTransaction API is termed a
resource-local entity manager.

A container-managed entity manager
must be a JTA entity manager.
JTA
entity managers are only specified for
use in Java EE containers.

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:

The EntityTransaction interface is used to control resource transactions on resource-local entity managers.

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:

  • how JTA entity managers ought to be used in an application server (which is typically the place where they are used).
  • how resource-local entity managers may be used in an application server.
  • how resource-local entity managers can be used in a Java SE application.
呢古 2024-11-24 01:40:50

您不需要手动实例化 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 your em field and forget about the other ones.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文