Spring transaction事务之roll back回滚

欢迎关注公众号:梦语路

试验方法:

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

试验过程:

         定义一个service方法如下:

         public SMSTimingcreateSMSTiming(SMSTiming smsTiming){

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

                   return s;

         }

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

            publicclass MyTestExceptionextends Exception

            publicclass TestExceptionextends Exception

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

 

测试1

public SMSTimingcreateSMSTiming(SMSTiming smsTiming){

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

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

       return s;

    }

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

测试2

        public SMSTimingcreateSMSTiming(SMSTiming smsTiming)throwsException{//受检异常(非运行异常)必须抛出

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

       try{

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

       }catch(Exception e){

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

       }

       return s;

    }

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

 

        

测试3

            public SMSTimingcreateSMSTiming(SMSTiming smsTiming)throwsRuntimeException{//运行异常(非受检异常)可以不抛出

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

       try{

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

       }catch(Exception e){

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

       }

       return s;

    }

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

测试4

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

 

 

资料:

1.       如流,新一代智能工作平台

2.        http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html

另,Tomcat源码剖析电子书:

代码和UML图:https://github.com/Aresyi/HowTomcatWorks 
排版更好的百度电子书:百度阅读

欢迎关注公众号:梦语路

### 关于捕获 `assert` 异常并手动设置事务回滚 在 Java 应用程序中处理 Spring 事务时,默认情况下,Spring 只会在遇到未检查异常(即继承自 `RuntimeException` 或者 `Error` 的异常)时自动回滚事务[^2]。对于通过断言 (`assert`) 抛出的 AssertionError,在默认配置下也会触发回滚。 然而,如果希望即使发生特定类型的异常也不让事务回滚,则可以通过编程方式控制这一行为: #### 使用 TransactionTemplate 显式管理事务边界 一种做法是利用 `TransactionTemplate` 来更细粒度地掌控事务的行为。这允许开发者定义自己的回调逻辑来决定何时提交或回滚事务。下面是一个简单的例子展示如何实现这一点: ```java @Autowired private PlatformTransactionManager transactionManager; public void performOperationWithCustomRollbackBehavior() { TransactionTemplate template = new TransactionTemplate(transactionManager); template.execute(status -> { try { // Your business logic here that might throw an assertion error. boolean shouldNotRollBackOnAssertionFailure = true; if (shouldNotRollBackOnAssertionFailure && status.isRollbackOnly()) { status.setRollbackOnly(false); // Prevent rollback on certain conditions. } return null; // or some result object } catch (AssertionError e) { // Handle the exception as needed without rolling back the transaction. log.error("Caught AssertionError but will not roll back.", e); return null; } }); } ``` 在这个例子中,当检测到 `AssertionError` 并且满足某些条件时,可以阻止事务标记为只读模式(`setRollbackOnly(true)`),从而防止其被回滚。 请注意这种方法并不推荐用于生产环境下的常规错误处理机制;它主要用于特殊场景下的调试目的或其他非常规需求。 另外值得注意的是,通常来说应该遵循框架的设计意图——即仅对不可恢复的情况才执行回滚操作。因此修改默认的回滚策略应当谨慎行事,并充分理解潜在的风险和后果。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值