`

spring抛出异常导致事物回滚失败

 
阅读更多

最近遇到了事务不回滚的情况,我还考虑说JPA的事务有bug? 我想多了.......  
  为了打印清楚日志,很多方法我都加tyr catch,在catch中打印日志。但是这边情况来了,当这个方法异常时候 日志是打印了,但是加的事务却没有回滚。

  例:  
   类似这样的方法不会回滚 (一个方法出错,另一个方法不会回滚) :  

[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. if(userSave){          
  2.     try {         
  3.         userDao.save(user);          
  4.         userCapabilityQuotaDao.save(capabilityQuota);         
  5.      } catch (Exception e) {          
  6.         logger.info("能力开通接口,开户异常,异常信息:"+e);         
  7.      }         
  8.  }  


下面的方法回滚(一个方法出错,另一个方法会回滚):

 

 

[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. if(userSave){         
  2.      try {          
  3.         userDao.save(user);          
  4.         userCapabilityQuotaDao.save(capabilityQuota);         
  5.        } catch (Exception e) {         
  6.         logger.info("能力开通接口,开户异常,异常信息:"+e);          
  7.         throw new RuntimeException();         
  8.      }          
  9. }  

或者:

[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. if(userSave){          
  2.     try {          
  3.         userDao.save(user);          
  4.         userCapabilityQuotaDao.save(capabilityQuota);          
  5.     } catch (Exception e) {          
  6.         logger.info("能力开通接口,开户异常,异常信息:"+e);          
  7.         TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();         
  8.     }         
  9.  }  

 

为什么不会滚呢??是对Spring的事务机制就不明白。!! 
   默认spring事务只在发生未被捕获的 runtimeexcetpion时才回滚。  
   spring aop  异常捕获原理:被拦截的方法需显式抛出异常,并不能经任何处理,这样aop代理才能捕获到方法的异常,才能进行回滚,默认情况下aop只捕获runtimeexception的异常,但可以通过  
    
配置来捕获特定的异常并回滚  
  换句话说在service的方法中不使用try catch 或者在catch中最后加上throw new runtimeexcetpion(),这样程序异常时才能被aop捕获进而回滚
  解决方案: 
  方案1.例如service层处理事务,那么service中的方法中不做异常捕获,或者在catch语句中最后增加throw new RuntimeException()语句,以便让aop捕获异常再去回滚,并且在service上层(webservice客户端,view层action)要继续捕获这个异常并处理
  方案2.在service层方法的catch语句中增加:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();语句,手动回滚,这样上层就无需去处理异常(现在项目的做法)

分享到:
评论

相关推荐

    Spring中的@Transactional事物回滚实例源码

    在这个例子中,`createUser`方法被标记为事务性的,如果在方法内部抛出未捕获的异常,Spring会自动回滚事务,确保数据一致性。 Spring事务管理的工作流程大致如下: 1. **AOP代理**:Spring使用AOP(面向切面编程)...

    spring-控制事物回滚

    本文将深入探讨“spring-控制事物回滚”这一主题,结合标签“源码”和“工具”,我们将从源代码层面理解Spring如何控制事务的回滚,并介绍一些实用的工具和技巧。 首先,我们需要了解什么是事务。事务是一组数据库...

    Spring异常捕获且回滚事务解决方案

    Spring 异常捕获且回滚事务解决方案 在 Spring 框架中,异常捕获和回滚事务是非常重要的概念。今天,我们将讨论如何在 Spring 中捕获异常并回滚事务。 首先,让我们了解一下 Spring 的事务机制。当我们在 Spring ...

    第十四章 Spring4 切面事物与事物通知与传播行为

    如果方法执行过程中抛出未检查异常(继承自RuntimeException的异常)或在@Transactional注解中指定的检查异常,Spring将自动回滚事务;反之,如果正常执行,事务将在方法结束时提交。 四、事务传播行为 事务传播...

    Spring中的声明式事物

    - `NEVER`:不允许在事务中运行,如果存在事务,抛出异常。 - `NESTED`:如果存在事务,则在嵌套事务内运行;若无事务,则行为类似于`REQUIRED`。 4. **事务的隔离级别** - `DEFAULT`:使用数据库默认的隔离级别...

    浅谈Spring中@Transactional事务回滚及示例(附源码)

    这种场景就可以使用@Transactional事物回滚。 二、checked异常和unchecked异常 checked异常和unchecked异常是Java语言中异常处理的两种类型。checked异常是指程序中可以预测的异常,例如无效的用户输入、文件不...

    spring.net 声明式事物管理小示例

    默认情况下,如果在事务中抛出未捕获的异常,事务将被回滚。你也可以自定义回滚规则,指定哪些异常应该导致事务回滚,哪些异常不应回滚。 7. **测试事务管理** 在 `SpringTransactionTest` 文件中,通常会包含...

    Spring事务管理Demo

    - `NEVER`:总是运行在非事务环境中,如果当前存在事务,则抛出异常。 - `NESTED`:如果当前存在事务,则在嵌套事务内运行;如果没有事务,则行为类似于`REQUIRED`。 Spring事务管理的隔离级别包括: - `DEFAULT`...

    spring事物传播测试表

    6. NEVER:如果当前存在事务,则抛出异常;如果不存在事务,则不开启新的事务。 7. NESTED:如果当前存在事务,则创建一个嵌套事务,它会在当前事务内部执行。如果当前没有事务,则行为类似于REQUIRED。 “事务传播...

    事物简单总结(偏向Spring事物)

    如果@Transactional注解的方法中抛出了未检查异常(继承自RuntimeException的异常)或在配置中明确指定的检查异常,Spring会自动回滚事务。如果抛出其他异常,Spring默认不会回滚事务,除非手动设置。 最后,我们来...

    spring 事物总结

    - 默认情况下,如果方法抛出未检查异常(继承自RuntimeException)或Error,Spring会自动回滚事务。 - 如果方法抛出受检查异常(非RuntimeException),则不会自动回滚,除非在@Transactional注解中指定了rollback...

    spring-mybatis.rar

    4. 事务超时:可以通过@Transactional注解的timeout属性设置事务的超时时间,超过该时间仍未完成则抛出异常并回滚事务。 5. 回滚规则:默认情况下,任何未捕获的运行时异常都会导致事务回滚。但也可以自定义回滚...

    Spring 管理事务(传播特性、隔离级别、readonly).rar

    如果不存在,则抛出异常。 - REQUIRES_NEW:无论当前是否存在事务,都创建一个新的事务,如果当前存在事务,则挂起当前事务。 - NOT_SUPPORTED:如果当前存在事务,则暂停当前事务;如果不存在,则不开启事务。 -...

    spring事物管理

    3. **PROPAGATION_MANDATORY**:强制使用当前事务,如果当前没有事务则抛出异常。这意味着,如果调用方不在一个事务中,被调用的方法将无法执行。 4. **PROPAGATION_REQUIRES_NEW**:总是开启一个新的事务,如果...

    spring 事物底层原理分析1

    - NEVER:不允许在事务中执行,如果当前存在事务,则抛出异常。 - NESTED:如果当前存在事务,则创建一个嵌套事务;如果没有事务,则按照REQUIRED行为处理。 理解这些传播行为有助于在多层方法调用中正确地管理事务...

    Spring Boot数据库事务控制.zip

    3. **事务回滚规则**:默认情况下,如果在@Transactional注解的方法中抛出未检查异常(继承自RuntimeException的异常)或者Error,Spring会自动回滚事务。对于受检查异常(非RuntimeException),需要显式地声明需要...

    spring and jdbc

    当方法抛出未检查异常(继承自`RuntimeException`的异常)或由`rollbackFor`指定的异常时,Spring会自动回滚事务。对于其他类型的检查异常,如果不指定`rollbackFor`,默认情况下事务不会回滚。 8. **Spring的AOP...

    spring事物传播propagation类别含义详解

    例如,领导必须管饭,不管饭没饭吃,我超级不开心,老子不干了(抛出异常)。 4. requires_new:如果当前有事务,则挂起该事物,并且自己创建一个新的事务给自己使用;如果当前没有事务,则跟required一样。例如,...

Global site tag (gtag.js) - Google Analytics