0

我有一种情况,我需要在全局 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();           

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

如果有人可以帮助我解决为什么在第一种情况下无法正常工作以及第二种方法是否可行,我将不胜感激?

4

3 回答 3

2

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

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

于 2012-11-03T15:59:11.673 回答
1

我假设在您的代码中,您之前以 SE 方式实例化了 mXAEntityManager,如下所示:

EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("resubEclipselink");

EntityManager mXAEntityManager = entityManagerFactory.createEntityManager();

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

@PersistenceContext(unitName = "resubEclipselink")

实体管理器 mXAEntityManager;

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

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

实体管理器 mXAEntityManager;

以及已经为您的会话 bean 设置的另一个默认值,如下所示:

@TransactionAttribute(TransactionAttributeType.REQUIRED)

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

于 2012-11-04T04:54:19.857 回答
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();                   
  }

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

于 2012-11-05T07:29:34.550 回答