问题现象比较奇怪,具体描述如下假如有三个业务接口 ServiceA 、ServiceB和ServiceC, 其中 ServiceA 中有一个方法实现如下 /**
* 事务属性配置为 PROPAGATION_REQUIRED
*/
void methodA() {
//其他业务操作 // 调用 ServiceB 的方法
try{
ServiceB.methodB();
}catch(Exception e){
} //其他业务操作
} ServiceB的methodB方法实现如下:/**
* 事务属性配置为 PROPAGATION_NESTED
*/
void methodB(){
ServiceC.methodC();
}ServiceC的methodC方法实现如下:/**
* 事务属性配置为 PROPAGATION_REQUIRED
*/
void methodC(){
//直接抛出异常
throw new RuntimeException();
}
此时调用methodA,则methodA执行结束spring框架代码提交事务时报如下异常:
[2018-02-24 17:02:29,444] (GlobalExceptionHandler.java:handle:35) [ERROR]: 运行时异常:
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been ed as rollback-only
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:720)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:521)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:291)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)但我觉得外部事务应当可以成功提交,不应当抛出异常(内部事务methodB出异常后不应当影响外部事务methodA的提交,因为methodB是嵌套事务,并且在methodA中进行了try/catch)
奇怪的是如果将methodB的实现改为:/**
* 事务属性配置为 PROPAGATION_NESTED
*/
void methodB(){
//ServiceC.methodC();
//不再调用methodC,直接抛异常
throw new RuntimeException();
}则最外层事务methodA可以成功提交,不知道为什么多了一层methodC调用就会抛出异常。
静等大神提示~
* 事务属性配置为 PROPAGATION_REQUIRED
*/
void methodA() {
//其他业务操作 // 调用 ServiceB 的方法
try{
ServiceB.methodB();
}catch(Exception e){
} //其他业务操作
} ServiceB的methodB方法实现如下:/**
* 事务属性配置为 PROPAGATION_NESTED
*/
void methodB(){
ServiceC.methodC();
}ServiceC的methodC方法实现如下:/**
* 事务属性配置为 PROPAGATION_REQUIRED
*/
void methodC(){
//直接抛出异常
throw new RuntimeException();
}
此时调用methodA,则methodA执行结束spring框架代码提交事务时报如下异常:
[2018-02-24 17:02:29,444] (GlobalExceptionHandler.java:handle:35) [ERROR]: 运行时异常:
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been ed as rollback-only
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:720)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:521)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:291)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)但我觉得外部事务应当可以成功提交,不应当抛出异常(内部事务methodB出异常后不应当影响外部事务methodA的提交,因为methodB是嵌套事务,并且在methodA中进行了try/catch)
奇怪的是如果将methodB的实现改为:/**
* 事务属性配置为 PROPAGATION_NESTED
*/
void methodB(){
//ServiceC.methodC();
//不再调用methodC,直接抛异常
throw new RuntimeException();
}则最外层事务methodA可以成功提交,不知道为什么多了一层methodC调用就会抛出异常。
静等大神提示~
解决方案 »
- String replaceAll方法替换*号出现异常
- dorado技术:dataset.disabledValidators不管用
- 师兄帮我介绍下
- 大家推荐一下判断两篇文章相似度方法?我尝试用lucene模糊搜索可以很好判断5、6个字的标题,但内容就不行了?有什么框架或方法可以实现?
- could not find main class program will exit问题
- ? "" : 是什么意思?
- 自认为挺有本事的Java高手请进,一个小问题.
- 急!急!急!大虾们来帮忙啊!JBoss如何快启动......
- java 问题 (看看无妨)!!
- 新手,help.....50分相送。
- idea+activiti
- 有了解用java实现类似头脑王者这种小程序的吗?
/**
* 事务属性配置为 PROPAGATION_REQUIRED
*/
void methodC(){
try {
//直接抛出异常
throw new RuntimeException();
} catch (Exception e) {
System.out.println("C抛出了异常");
}
}
/**
* 事务属性配置为 PROPAGATION_REQUIRED
*/
void methodC(){
try {
//直接抛出异常
throw new RuntimeException();
} catch (Exception e) {
System.out.println("C抛出了异常");
}
}这个方法的异常我需要throw出去,不能这样catch住
你这个异常大概原因是,C抛出异常,AOP已经标记事务要回滚,但异常到A却被捕获,代码继续执行,然后提交事务,就会抛出该异常
像在题目中描述的那样,如果在methodB中直接抛出异常而不调用methodC,则methodA可以提交成功,想不通为什么
那得看看那spring事务传播机制配的什么了
那得看看那spring事务传播机制配的什么了methodA配置的REQUIRED,methodB配置的NESTED,methodC配置的REQUIRED,大神请进一步指导