Spring transaction事务之roll back回滚: rollback-for

本文通过六个具体的测试案例,详细探讨了Spring框架中事务回滚的机制,特别是针对不同的异常类型(如运行时异常和受检异常)以及如何通过配置rollback-for属性来控制哪些异常会导致事务回滚。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

试验方法:

         写一个单元测试,调用一个service层方法(发生对数据库进行写操作的方法--insert、update、delete)即可.

  applicationContext.xml 样子(如何设置rollback-for)

  1. <!-- 
  2.         spring事务管理 方法一-->  
  3.     <bean id="transactionManager"  
  4.         class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
  5.         <property name="dataSource" ref="dataSource" />  
  6.     </bean>  
  7.     <aop:config>  
  8.         <aop:pointcut id="serviceOperation" expression="execution(*  
  9.         com.*.service.*.*(..))" />  
  10.         <aop:advisor pointcut-ref="serviceOperation" advice-ref="txAdvice" />  
  11.     </aop:config>  
  12.   
  13.     <tx:advice id="txAdvice" transaction-manager="transactionManager">  
  14.         <tx:attributes>  
  15.             <tx:method name="insert*" rollback-for="Exception" />  
  16.             <tx:method name="save*" rollback-for="Exception" />  
  17.             <tx:method name="update*" rollback-for="Exception" />  
  18.             <tx:method name="delete*" rollback-for="Exception" />  
  19.             <tx:method name="*" read-only="true" rollback-for="Exception" />  
  20.         </tx:attributes>  
  21.     </tx:advice>  


试验过程:

         定义一个service方法如下:

         public SMSTiming createSMSTiming(SMSTiming smsTiming){

                   SMSTiming s= this.getSmsTimingDAO().createSMSTiming(smsTiming);

                   return s;

         }

 

         定义二个异常(先默认配置TestException为Spring事务回滚异常):

            publicclass MyTestException extends Exception

            publicclass TestException extends Exception

 

         注意看下:每次这个方法的不同处(抛出的异常不同)。

 

测试1

public SMSTiming createSMSTiming(SMSTiming smsTiming){

       SMSTiming s= this.getSmsTimingDAO().createSMSTiming(smsTiming);

       int i = 4/0; //人为产生异常(实际这里抛出了ArithmeticException运行异常)

       return s;

    }

测试1结果:会事务回滚----数据库中未插入新数据。

 

 

测试2

        public SMSTiming createSMSTiming(SMSTiming smsTiming) throws Exception{//受检异常(非运行异常)必须抛出

       SMSTiming s= this.getSmsTimingDAO().createSMSTiming(smsTiming);

       try{

           int i = 4/0; //人为产生异常

       }catch(Exception e){

           thrownew Exception ("");//抛出Exception异常

       }

       return s;

    }

测试2结果:不会事务回滚----数据库中插入新数据。

 

        

测试3

            public SMSTiming createSMSTiming(SMSTiming smsTiming) throws RuntimeException{//运行异常(非受检异常)可以不抛出

       SMSTiming s= this.getSmsTimingDAO().createSMSTiming(smsTiming);

       try{

           int i = 4/0; //人为产生异常

       }catch(Exception e){

           thrownewRuntimeException("");//抛出RuntimeException异常

       }

       return s;

    }

测试3结果:会事务回滚----数据库中未插入新数据

 

测试4

        public SMSTiming createSMSTiming(SMSTiming smsTiming) throws TestException{//受检异常(非运行异常)必须抛出

       SMSTiming s= this.getSmsTimingDAO().createSMSTiming(smsTiming);

       try{

           int i = 4/0; //人为产生异常

       }catch(Exception e){

           thrownewTestException("");//抛出TestException异常

       }

       return s;

    }

测试4结果:会事务回滚----数据库中未插入新数据。

 

测试5

    public SMSTiming createSMSTiming(SMSTiming smsTiming) throws MyTestException{//受检异常(非运行异常)必须抛出

       SMSTiming s= this.getSmsTimingDAO().createSMSTiming(smsTiming);

       try{

           int i = 4/0; //人为产生异常

       }catch(Exception e){

           thrownewMyTestException("");//抛出MyTestException异常

       }

       return s;

    }

 测试5结果:不会事务回滚----数据库中插入新数据。

 

测试6

    public SMSTiming createSMSTiming(SMSTiming smsTiming) throws MyTestException{//受检异常(非运行异常)必须抛出 (注意:此时spring指定配置此异常回滚)

       SMSTiming s= this.getSmsTimingDAO().createSMSTiming(smsTiming);

       try{

           int i = 4/0; //人为产生异常

       }catch(Exception e){

           thrownewMyTestException("");//抛出MyTestException异常

       }

       return s;

    }

 测试6结果:会事务回滚----数据库中未插入新数据。

 

 

试验总结:

测试1、测试3、测试4、测试6会进行事务回滚;测试2、测试5不会进行事务回滚。

 

为什么会这样?因为是异常的类型(受检异常、运行时异常)不同或使用了Springrollback-for配置

 

测试1和测试3是因为抛出了运行时异常,会事务回滚。

 

测试4和测试5、测试6分别抛出受检异常TestException、MyTestException,那为什么测试4和测试6会事务回滚呢?

因为是我们在Spring事务配置中指定了此异常(指定rollback-for)。



又一篇文章:

昨天同事说Spring的Transactional必须添加rollbackFor = Exception.class,否则事务不会回滚。但我原来试过,抛出RuntimeException时是会回滚的。于是查看Spring的Transactional的API文档,发现下面这段:

If no rules are relevant to the exception, it will be treated like DefaultTransactionAttribute (rolling back on runtime exceptions).

后面又试了下发现,如果不添加rollbackFor等属性,Spring碰到Unchecked Exceptions都会回滚,不仅是RuntimeException,也包括Error。


=============================================

Spring框架的事务基础架构代码将默认地  在抛出运行时和unchecked exceptions时才标识事务回滚。 也就是说,当抛出一个RuntimeException 或其子类例的实例时。(Errors 也一样 - 默认地 - 标识事务回滚。)从事务方法中抛出的Checked exceptions将  被标识进行事务回滚

<think>好的,我现在要解决用户关于Spring框架中事务配置项`rollback-on-commit-failure`的问题。首先,我需要确定用户具体想知道什么。他们提到的是这个配置的作用和用法,所以我需要先理解这个配置项在Spring事务管理中的角色。 根据用户提供的引用内容,特别是引用[1]里提到的回滚规则,用户可能已经知道Spring允许通过配置定义哪些异常会触发回滚,而不是在代码中硬编码。而`rollback-on-commit-failure`可能和提交阶段发生的错误有关,比如数据库在提交时出现故障,这时候是否需要回滚。 接下来,我需要回忆Spring事务管理的相关知识。Spring事务管理通常依赖于底层的事务管理器,比如DataSourceTransactionManager或者JTA。提交失败时的处理可能由这些事务管理器的配置决定。例如,某些数据库在提交时可能会抛出异常,这时候事务管理器需要决定是否标记事务回滚。 查阅文档的话,`rollback-on-commit-failure`可能是一个配置属性,用于指定在提交事务过程中发生异常时是否回滚。例如,当数据库连接在commit()时出现错误,比如网络中断或数据库崩溃,事务管理器可以根据这个配置决定是否回滚事务。默认情况下,可能某些事务管理器不会自动回滚,因为提交阶段通常被认为是最终操作,但某些情况下可能需要显式配置。 然后,我需要确认这个配置项的具体使用方式。例如,在Spring Boot中,可能需要通过配置DataSourceTransactionManager的相关属性,或者在配置JTA事务管理器时设置。例如,在配置文件中添加类似`spring.transaction.rollback-on-commit-failure=true`这样的属性。 此外,用户提供的引用[3]提到了Seata的配置,可能涉及分布式事务,但用户的问题集中在Spring框架本身,所以可能需要排除Seata相关的内容,除非这个配置项与分布式事务有关联。 再考虑使用场景:当应用在高并发或不可靠的网络环境下运行时,提交阶段可能失败,这时候正确配置`rollback-on-commit-failure`可以确保数据一致性,避免部分提交导致的数据不一致问题。 最后,需要验证这些信息是否正确,可能需要参考Spring官方文档或可靠的资料。例如,Spring的DataSourceTransactionManager是否有这样的配置项,或者是否是特定于某些数据库或驱动程序的设置。例如,PostgreSQL在提交时可能会抛出异常,这时候是否需要特别处理。 总结:`rollback-on-commit-failure`的作用是在事务提交过程中发生异常时决定是否回滚事务,用法通常是在事务管理器的配置中启用该选项,以确保提交失败的事务被正确回滚,保持数据一致性。</think>在Spring框架中,`rollback-on-commit-failure`是事务配置中一个重要的参数,主要用于控制**事务提交阶段发生异常时是否触发回滚**。以下是具体作用和用法说明: --- ### 一、作用解析 1. **提交阶段异常处理** 当事务管理器(如`DataSourceTransactionManager`)执行`commit()`操作时,若数据库返回提交失败(例如网络中断、锁冲突、唯一约束违反等),该参数决定是否将事务标记为回滚。默认情况下,某些事务管理器可能不会自动回滚,需显式配置此参数[^1]。 2. **数据一致性保障** 启用此配置后,即使提交阶段失败,Spring仍会尝试将事务标记为回滚状态,避免数据库处于不一致状态。 --- ### 二、配置方式 #### 1. 基于XML配置 ```xml <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> <property name="rollbackOnCommitFailure" value="true"/> </bean> ``` #### 2. 基于Java注解(Spring Boot) 在`application.properties`或`application.yml`中配置: ```properties # 针对DataSourceTransactionManager spring.transaction.rollback-on-commit-failure=true ``` --- ### 三、典型场景 1. **分布式事务提交失败** 在分布式数据库或微服务架构中,提交可能因跨服务调用失败而中止,启用此参数可确保全局事务一致性[^3]。 2. **数据库驱动兼容性问题** 某些数据库驱动(如PostgreSQL)在提交失败时可能不会自动回滚,需依赖此配置强制回滚--- ### 四、注意事项 - **与编程式回滚的协作** 若通过`TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()`手动回滚,此配置不会覆盖该行为[^1]。 - **性能影响** 频繁的提交失败回滚可能增加系统负载,需结合日志监控分析根本原因。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值