3

我有一个带有 Bean 管理事务的 EJB:

@Singleton
@TransactionManagement(TransactionManagementType.BEAN)
public class BmtBean {

  @Resource
  private DataSource ds1;

  @Resource
  private SessionContext sessionCtx;

  @EJB
  private CmtBean cmtBean;

  public void callCmtBean() {
    Connection conn1 = null;
    try {
      conn1 = ds1.getConnection();
      // create a PreparedStatement and execute a query
      // process result set
      while(resultSet.next()) {
        // map resultSet to an entity
        Entity entity = mapResultSetToEntity(resultSet);
        sessionCtx.getUserTransaction().begin();
        // pass an entity to another EJB,
        // that operates on a different JTA data source
        cmtBean.call(entity);
        sessionCtx.getUserTransaction().commit();
      }
    } finally {
      // release connection
    }
  }
}

还有另一个具有容器管理事务的 bean:

@Singleton
@TransactionManagement(TransactionManagementType.CONTAINER)
public class CmtBean {

  @PersistenceContext
  private EntityManager em;

  @TransactionAttribute(TransactionAttributeType.MANDATORY)
  public void call(Entity entities) {
    //persist passed entities
    //em.flush()
    //em.clear();
  }

}

调用cmtBean#call不会导致TransactionRequiredException,因为在此之前我开始了UserTransaction. 但是当em#flush被调用时,会抛出这个异常:

原因:javax.resource.spi.ResourceAllocationException:分配连接时出错。原因:java.lang.IllegalStateException:本地事务已经有 1 个非 XA 资源:无法添加更多资源。

在挖掘了一些 EclipseLink 代码后,我看到调用em#flush()它时会尝试从中获取新连接dataSource,但没有成功。

这是错误还是预期行为?我怎样才能解决这个问题?

更新:
查看更新的代码示例。

另外,我必须强调,我确实使用了 2 个非 XA JTA 数据源。但是由于BmtBean默认情况下的连接设置为autocommit,因此在CmtBean调用时,事务必须已经提交。

4

0 回答 0