Java 如何捕获JTA事务内部抛出的异常?
我使用的是Spring 3.0.5、Hibernate 3.6.7和Atomikos Transactionessentials 3.7.0。使用applicationContext.xml中的AOP配置的事务。 一切正常。(提交、回滚) 我的意图是在jta事务中抛出一个特定的异常。 通过这种方式,应该回滚事务,我可以获得有关回滚原因的一些详细信息 问题是,我能捕捉到的唯一异常是atomikos抛出的回滚事务,它告诉我该事务被意外回滚 如何在事务之外获取自己的异常 这里有一个小例子,因为我不知道我的解释是否足够好。 这只是为了说明我的意图。请不要评论任何打字错误 特定异常(也可能是一些标准异常): 声明要引发异常的方法的接口:Java 如何捕获JTA事务内部抛出的异常?,java,spring,jpa,jta,Java,Spring,Jpa,Jta,我使用的是Spring 3.0.5、Hibernate 3.6.7和Atomikos Transactionessentials 3.7.0。使用applicationContext.xml中的AOP配置的事务。 一切正常。(提交、回滚) 我的意图是在jta事务中抛出一个特定的异常。 通过这种方式,应该回滚事务,我可以获得有关回滚原因的一些详细信息 问题是,我能捕捉到的唯一异常是atomikos抛出的回滚事务,它告诉我该事务被意外回滚 如何在事务之外获取自己的异常 这里有一个小例子,因为我不知道
public interface MyInterface {
Object someJtaTransactionMethod(String param) throws MySpecialException;
}
实现接口的类:
public class MyClass implements MyInterface {
Object someJtaTransactionMethod(String param) throws MySpecialException {
// some operations with some errorstate detected
// so throw the exception:
throw new MySpecialException("Things went terribly wrong!");
// some other code
}
}
还有一些调用函数并捕获异常的代码
public class Caller {
@Autowired
private MyInterface callee;
public void test() {
try {
callee.someJtaTransactionMethod("Some test");
} catch (MySpecialException mex) {
// I want to get here
} catch (Exception ex) {
// but I only get here
}
}
}
这可能吗
更新:当然我看了一下异常原因。异常本身是org.springframework.transaction.UnexpectedRollbackException。原因属于类javax.transaction.RollbackTransaction,并且有一个原因com.atomikos.icatch.RollbackException
我认为发生的情况是,atomikos注意到异常并执行回滚(根据需要),但随后atomikos(可能还有其他jta实现)抛出异常,指示事务被回滚(意外地),我的异常消失
更新2:有趣的是,如果我没有做任何必须回滚的事情,我可以根据需要捕获我的异常
更新3和解决方案:JB Nizet向我指出了解决方案。事实上,我的事务并没有像我所怀疑的那样回滚,但由于我抛出异常的原因,我得到了一个违禁违规,因此atomikos在提交时抛出了它的异常。现在,我已将事务配置为回滚我的异常,所有操作都按照预期和期望的方式进行。在抛出从Exception而不是MyException继承的MySpecialException时,我觉得这是一种类型
否则,捕获MySpecialException而不是MyException 您的异常是运行时异常还是已检查异常 如果抛出运行时异常,Spring默认回滚;如果抛出选中的异常,Spring默认提交 从堆栈跟踪来看,您的异常似乎是一个已检查的异常,因此Spring尝试提交,但无法提交,因为JTA TM(Atomikos)拒绝提交(例如,由于超时)
因此,如果希望此异常导致回滚,请将其设置为运行时异常,或在@Transactional注释的
rollbackor
属性中声明它。如果它一定不会导致回滚,那么试着找出Atomikos拒绝提交的原因(超时时间太短,其他原因……日志可能会有所帮助)。我已经说过,这只是一个示例,拼写错误不是问题所在。我真正的代码会编译并最终尝试捕获正确的异常(否则编译器会告诉我…)更正它…我不知道Atomikos,但他们是否会捕获您的异常并抛出自己的异常作为其原因?您是否分析了异常的getCause()方法的返回(从您的第二个捕获中)?是的,我详细查看了异常(在开发过程中不止一次),并尝试对其进行调试,但找不到任何东西。。。更新后可以提供堆栈跟踪和正在使用的框架版本吗?一些有趣的信息。通常,如果我遇到这样的异常,我会调试到atomikos中并找到真正的原因(例如一些hibernate或jdbc异常)。明天上午我将继续研究这个问题。。。。。我再也睁不开眼睛了。非常感谢。你救了我一天。我刚刚将我的异常更改为从RuntimeException继承,现在一切正常。我之前没有注意到,当我抛出自己的异常时,atomikos没有回滚,而且由于抛出异常,我昨天不知何故无法调试到atomikos中。
public class Caller {
@Autowired
private MyInterface callee;
public void test() {
try {
callee.someJtaTransactionMethod("Some test");
} catch (MySpecialException mex) {
// I want to get here
} catch (Exception ex) {
// but I only get here
}
}
}