我有一个参与全局事务的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"
有没有其他方法可以解决这个问题?
答案 0 :(得分:2)
您可以使用带有@TransactionAttribute(REQUIRES_NEW)
注释的第二个EJB来使用CMT,您可以在其中放置可能失败的代码。您必须从其他EJB调用此EJB。
容器为代码创建一个新事务,如果失败则将回滚。
答案 1 :(得分:1)
事务上下文不会传播到BTM。您的bean也不会成为全局事务的一部分。因此,当您的全局事务失败时,您的更改仍可以提交。
我不熟悉websphere设置但我会重新检查连接是否正确。我希望注入BTM还是以某种方式从CMT传递连接?如果连接设置为支持jta / global事务,我可以尝试检查容器配置。
或者,在开始使用连接之前,您是否启动了一些UserTransaction.begin()
?
如果这样做仍然无法解决您的问题。
适合您使用嵌套事务,但Java EE不支持它们。就好像WebShere有一些特定于提供者的方式来运行它们(我不知道它的能力)。
然后最简单的方法是使用CMT REQUIRES_NEW
,但即使全局事务已回滚,它也有提交db更改的缺点。
可能需要更改某些应用程序。