在XA事务中执行工作

时间:2012-11-03 13:59:59

标签: jpa-2.0 eclipselink jta

我有一种情况需要在全局tx中执行一些工作。

出于这个原因,我在persistence.xml中定义了以下PersistenceUnit来获取jta entityManager。

<persistence-unit name="resubEclipselink" transaction-type="JTA">
    <jta-data-source>jdbc/XADataSource</jta-data-source>
    ...
</persistence-unit>

现在坚持下去,我试着按照以下步骤进行#1:

    if(isXA()){
        mXAEntityManager.persist(entity);
        mXAEntityManager.flush(); 
    }

事情因例外而失败

javax.persistence.TransactionRequiredException: 
Exception Description: No transaction is currently active
    at       
org.eclipse.persistence.internal.jpa.transaction.EntityTransactionWrapper.throwCheckTransactionFailedException(EntityTransactionWrapper.java:113)

我在开始用户交易之前就有了同样的理由。

所以我尝试了另一种方法#2:

// get the transactional unit of work or null.
UnitOfWork uow = mEntityManager.getUnitOfWork();
    uow.registerObject(entity);
uow.writeChanges(); 
uow.commit();           

这种作品,但我不确定这是否是正确的方法。

如果有人可以帮助我解决为什么在第一种情况下不起作用以及第二种方法是否合适的话,我将不胜感激?

3 个答案:

答案 0 :(得分:2)

第一种方法应该有效,配置设置可能不会告诉Eclipselink关于交易。检查是否已指定此处描述的目标服务器属性 http://eclipse.org/eclipselink/documentation/2.4/jpa/extensions/p_target_server.htm 因为这将用于获取事务管理器并注册活动事务。

一旦在事务中正确注册,就不需要直接在UnitOfWork上调用commit。

答案 1 :(得分:1)

我假设你的代码中早些时候你用这样的SE方式实例化了mXAEntityManager:

  

EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory(“resubEclipselink”);

     

EntityManager mXAEntityManager = entityManagerFactory.createEntityManager();

在部署在应用程序服务器中的EE应用程序中不起作用。您应该使用依赖注入替换这两行:

  

@PersistenceContext(unitName =“resubEclipselink”)

     

EntityManager mXAEntityManager;

以便您允许容器注入持久性上下文(mXAEntityManager)以及您需要的所有事务管理。因此,没有flush()没有begin()不再需要commit()调用,只要你没有弄乱已经设置为这样的默认值:

  

@PersistenceContext(unitName =“resubEclipselink”,type = PersistenceContextType.TRANSACTION)

     

EntityManager mXAEntityManager;

以及为会话bean设置的另一个默认值如下:

  

@TransactionAttribute(TransactionAttributeType.REQUIRED)

请记住,这些默认值是使开发EE应用程序遵循范式“异常配置”的原因。

答案 2 :(得分:0)

我的场景以我需要根据其他一些条件决定事务边界的方式运行。

所以基本上我需要让我的应用程序管理的实体管理器登记到全局tx并执行一些工作单元作为全局tx的一部分。所以我实际上得到一个实体管理器并将其设置为使用ExternalTransactionController。

            if(isXA){
                    this.mEntityManager = JpaHelper.getEntityManager(Persistence.createEntityManagerFactory(XA_PU).

                                            createEntityManager());

                    this.mServerSession = this.mEntityManager.getServerSession();
                    this.mServerSession.getLogin().setUsesExternalTransactionController(true);
                    this.mServerSession.getLogin().setUsesExternalConnectionPooling(true);
            }else{
                   this.mEntityManager = JpaHelper.getEntityManager(Persistence.createEntityManagerFactory(RESORUCE_LOCAL_PU).
                                                                                                                            createEntityManager());

                    this.mEntityTransaction = this.mEntityManager.getTransaction();
                    this.mServerSession = this.mEntityManager.getServerSession();
            }

然后获得并执行工作单元......

  // get the transactional unit of work or null.
  UnitOfWork uow = mEntityManager.getUnitOfWork();

  // resource-local em
  if(uow == null){
          mEntityTransaction.begin(); 
          mEntityManager.persist(entity); 
          mEntityTransaction.commit();
  }else{                  
          uow.registerObject(entity);
          uow.writeChanges(); 
          uow.commit();                   
  }

正如我之前提到的,我对这种方法并不太自信,所以如果有人能够对此进行审核并让我知道这种方法是否存在一些缺陷,我将非常感激...