我有一个带有 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
调用时,事务必须已经提交。