分布式事务中的合法回滚:可能吗?
问题描述:
我有一个涉及全局事务的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);
}
这样,我只是撤消我的本地数据库修改,但我也不会传播这种故障转移到外面。反正这程序失败为:
“保存点在分布式事务中禁止”有没有办法解决这个问题的另一种方法?
答
事务上下文不会传播到BTM。你的bean也不会成为全局事务的一部分。所以,如果全局事务失败,您的更改仍可能被提交。
我不熟悉websphere设置,但我会重新检查连接。我期望注入到BTM中,还是通过CMT以某种方式传递连接?如果连接设置为支持jta /全局事务,我可以尝试检查容器配置。 或者,在开始使用连接之前,您是否启动了一些UserTransaction.begin()
? 如果这项工作仍然无法解决您的问题。
适合你的是使用嵌套事务,但它们在Java EE中不受支持。就像WebShere有一些提供者特定的方式来运行它们(我不知道它的能力)。
然后,最简单的方法是使用CMT REQUIRES_NEW
,但它的缺点是即使全局事务被回滚也会提交数据库更改。
也许需要一些应用程序设计变更。
答
您可以通过使用第二个注释为@TransactionAttribute(REQUIRES_NEW)
的EJB来使用CMT,您可以在其中放置可能失败的代码。您必须从另一个EJB调用此EJB。
容器为代码创建一个新事务,如果失败,它将回滚。
如果新事务有效,新事务也会提交。请注意,新交易与第一笔交易无关,并且如果某件事使第一笔交易回滚(出于另一原因),则新笔交易仍将承诺。 – kaczyns