JPA:关于entityManager.joinTransaction的问题

时间:2011-07-15 07:50:41

标签: java jpa

假设我们声明一个应用程序管理的实体管理器,如下所示(类似的版本可以在http://download.oracle.com/docs/cd/E19798-01/821-1841/bnbqy/index.html找到):

@PersistenceUnit EntityManagerFactory emf;
@Resource UserTransaction utx;
protected void doPost(HttpServletRquest req,...)
   em = emf.createEntityManager();
   try {
     utx.begin(); //(1)
     em.persist(SomeEntity);
     utx.commit();
   } catch (Exception e) {
     utx.rollback();
   }

虽然代码工作正常,但是SUN架构师的几张幻灯片(例如:http://www.scribd.com/doc/6616366/TS49452007JavaEE)表示该块是 buggy ,而“em.joinTransaction()”应该在之后添加第(1)行(幻灯片#50)。

如果发生异常,持久性上下文不一致,我们只需关闭 em ,那么这里有什么潜在的错误?

我非常感谢任何我失踪的建议。感谢。

2 个答案:

答案 0 :(得分:4)

是的,从JTA的角度来看,您展示的代码是错误的。

您需要通过调用em.joinTransaction()告诉EM您希望它成为分布式事务的一部分。如果不调用该方法,则将断开用户事务和EM事务。该方法的javadoc状态:

  

向EntityManager表明JTA事务处于活动状态。

您还可以看到,当您调用em.joinTransaction时,EM不需要启动事务。如果您不在JTA环境中,那么您需要调用em.getTransaction()。begin()和em.getTransaction.commit(),但由于您处于JTA事务中,因此UserTransaction负责启动,承诺或回滚。


关于第二个问题,你在那里的代码没有问题,好像有一个例外,你根本就没有调用EM。 但是如果有异常,您可以(并且应该)调用的唯一方法是em.close()。如果你尝试做任何其他事情,例如调用em.find(),EM将抛出一个InvalidStateException。

我希望我写的很清楚... JTA是一个复杂的怪物。

答案 1 :(得分:0)

我认为上述代码的问题是有时它不起作用。虽然它在我的试验中起作用(我尝试使用Glassfish / EclipseLink),但在其他情况下它可能不起作用(例如:http://netbeans.org/bugzilla/show_bug.cgi?id=90031)。

我遗漏的一件事(由@Augusto回答)是使用“em.joinTransaction”,我们不仅要求em创建的“持久上下文”与utx相同,而且还将em注册到utx,以便utx.commit,em会将其内容刷新到db。

我很满意@Augusto的答案,但由于我无法登录创建问题的帐户,我无法点击“接受”按钮;对于那个很抱歉。