分布式事务中的合法回滚:可能吗?

Legit rollback in a distributed transaction: possible?

我有一个涉及全局事务的 EJB。 有一部分代码,如果它失败了,我想显式回滚,尽管我不希望整个事务失败。

由于在 CMT 中禁止回滚,我创建了一个 BMT 并尝试了以下代码:

connection.setAutoCommit(false);
Savepoint sp= connection.setSavepoint();
try{
    //my code editing DB that could possibly fail
}catch(SomeException ex){
    connection.rollback(sp);
}

这样我只是撤消我的本地数据库修改,但我也不会将此失败传播到外部。无论如何,这个程序失败了:

"Savepoint is forbidden in a distributed transaction"

是否有其他方法可以解决这个问题?

您可以通过使用带有 @TransactionAttribute(REQUIRES_NEW) 注释的第二个 EJB 来使用 CMT,您可以在其中放置可能失败的代码。您必须从其他 EJB 调用此 EJB。

容器为代码创建一个新事务,如果失败将回滚。

事务上下文不会传播到 BTM。您的 bean 也不会成为全局事务的一部分。因此,当您的全局事务失败时,您的更改仍然可以提交。

我不熟悉 websphere 设置,但我会重新检查连接是否正确。我希望被注入到 BTM,或者你是否以某种方式从 CMT 传递连接?如果连接设置为支持 jta/global 事务,我可以尝试检查容器配置。 还是在开始使用连接之前启动 some UserTransaction.begin()? 即使这有效,也不能解决您的问题。

适合您的方法是使用嵌套事务,但 Java EE 不支持它们。只是如果 WebShere 有一些提供者特定的方式如何 运行 它们(我不知道它的能力)。

那么最简单的方法就是使用 CMT REQUIRES_NEW,但它的缺点是即使全局事务已回滚,也会提交数据库更改。

也许需要更改一些应用程序设计。