一、结论
Spring的事务管理默认只对出现运行期异常(java.lang.RuntimeException及其子类)进行回滚。
如果一个方法抛出Exception或者Checked异常,Spring事务管理默认不进行回滚。
关于异常的分类一下详细介绍:
1、基本概念
看java的异常结构图
Throwable是所有异常的根,java.lang.Throwable
Error是错误,java.lang.Error
Exception是异常,java.lang.Exception
2、Exception
一般分为Checked异常和Runtime异常,所有RuntimeException类及其子类的实例被称为Runtime异常,不属于该范畴的异常则被称为CheckedException。
①Checked异常
只有java语言提供了Checked异常,Java认为Checked异常都是可以被处理的异常,所以Java程序必须显示处理Checked异常。如果程序没有处理Checked异常,该程序在编译时就会发生错误无法编译。这体现了Java的设计哲学:没有完善错误处理的代码根本没有机会被执行。对Checked异常处理方法有两种
(1) 当前方法知道如何处理该异常,则用try...catch块来处理该异常。
(2) 当前方法不知道如何处理,则在定义该方法是声明抛出该异常。
package cn.xy.test; import java.io.IOException; /** * Checked异常测试方法 * * @author xy */ public class CheckedExceptionMethods { // 总异常类,既有checkedException又有RuntimeException,所以其中的checkedException必须处理 public void method1() throws Exception { System.out.println("我是抛出异常总类的方法"); } // 捕获并处理这个异常 public void testMethod1_01() { try { method1(); } catch (Exception e) { e.printStackTrace(); } } // 把异常传递下去 public void testMethod1_02() throws Exception { method1(); } public void testMethod1_03() throws Exception { throw new Exception(); } public void testMethod1_04() { try { throw new Exception(); } catch (Exception e) { e.printStackTrace(); } } // checkedException典型代表IOException public void method2() throws IOException { System.out.println("我是抛出IO异常的方法"); } public void testMethod2_01() { try { method2(); } catch (Exception e) { e.printStackTrace(); } } public void testMethod2_02() throws Exception { method2(); } }
我们比较熟悉的Checked异常有
Java.lang.ClassNotFoundException
Java.lang.NoSuchMetodException
java.io.IOException
②RuntimeException
Runtime如除数是0和数组下标越界等,其产生频繁,处理麻烦,若显示申明或者捕获将会对程序的可读性和运行效率影响很大。所以由系统自动检测并将它们交给缺省的异常处理程序。当然如果你有处理要求也可以显示捕获它们。
package cn.xy.test; /** * 运行时异常测试方法 * * @author xy */ public class RuntimeExcetionMethods { public void method3() throws RuntimeException { System.out.println("我是抛出运行时异常的方法"); } public void testMethod3_01() { method3(); } public void testMethod1_02() { throw new RuntimeException(); } }
我们比较熟悉的RumtimeException类的子类有
Java.lang.ArithmeticException
Java.lang.ArrayStoreExcetpion
Java.lang.ClassCastException
Java.lang.IndexOutOfBoundsException
Java.lang.NullPointerException
3、Error
当程序发生不可控的错误时,通常做法是通知用户并中止程序的执行。与异常不同的是Error及其子类的对象不应被抛出。
Error是throwable的子类,代表编译时间和系统错误,用于指示合理的应用程序不应该试图捕获的严重问题。
Error由Java虚拟机生成并抛出,包括动态链接失败,虚拟机错误等。程序对其不做处理。
二、改变默认方式
(1)、在@Transaction注解中定义noRollbackFor和RollbackFor指定某种异常是否回滚。
@Transaction(noRollbackFor=RuntimeException.class)
@Transaction(RollbackFor=Exception.class)
这样就改变了默认的事务处理方式。
如果配置了rollbackFor 和 noRollbackFor 且两个都是用同样的异常,那么遇到该异常,还是回滚;
rollbackFor 和noRollbackFor 配置也许不会含盖所有异常,对于遗漏的按照Check Exception 不回滚,unCheck Exception回滚
(2)、在txAdive中增加rollback-for,里面写自己的exception,例如自己写的exception:
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" rollback-for="com.cn.untils.exception.XyzException"/>
</tx:attributes>
</tx:advice>
或者
定义不会滚的异常
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="update*" no-rollback-for="IOException"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
(3)、spring的事务边界是在调用业务方法之前开始的,业务方法执行完毕之后来执行commit or rollback(Spring默认取决于是否抛出runtime异常).
如果抛出runtime exception 并在你的业务方法中没有catch到的话,事务会回滚。
一般不需要在业务方法中catch异常,如果非要catch,在做完你想做的工作后(比如关闭文件等)一定要抛出runtime exception,否则spring会将你的操作commit,这样就会产生脏数据.所以你的catch代码是画蛇添足。
如:
try {
//bisiness logic code
} catch(Exception e) {
//handle the exception
}
由此可以推知,在spring中如果某个业务方法被一个 整个包裹起来,则这个业务方法也就等于脱离了spring事务的管理,因为没有任何异常会从业务方法中抛出!全被捕获并吞掉,导致spring异常抛出触发事务回滚策略失效。
不过,如果在catch代码块中采用页面硬编码的方式使用spring api对事务做显式的回滚,这样写也未尝不可
三、启示
这就要求我们在自定义异常的时候,让自定义的异常继承自RuntimeException,这样抛出的时候才会被Spring默认的事务处理准确处理。
相关推荐
在这个“spring简单实例 事务回滚”的案例中,我们将深入探讨Spring如何处理事务回滚,以及它是如何在Java源码层面实现这一功能的。 首先,让我们理解什么是事务。在数据库操作中,事务是确保数据一致性的重要机制...
7. **实现事务回滚**:当在@Transactional注解的方法中发生异常时,Spring会自动回滚事务。例如,如果在保存数据时发生错误,整个事务将被回滚,保证数据的一致性。 8. **测试与调试**:完成整合后,通过编写单元...
四、事务回滚与AOP Spring使用代理(Proxy)和面向切面编程(AOP)来实现`@Transactional`注解的功能。当Spring容器创建一个`@Transactional`标注的方法时,它会创建一个动态代理对象,该代理对象会在方法调用前后...
Spring 异常捕获且回滚事务解决方案 在 Spring 框架中,异常捕获和回滚事务是非常重要的概念。今天,我们将讨论如何在 Spring 中捕获异常并回滚事务。 首先,让我们了解一下 Spring 的事务机制。当我们在 Spring ...
"spring-控制事物回滚"这个主题主要涉及Spring如何在出现异常时自动或手动触发事务的回滚,以及如何配置和使用Spring的事务管理机制。我们将深入探讨Spring事务管理的原理、API使用以及在实际开发中的应用。 首先,...
子线程任务发生异常,主线程事务如何回滚? 本文将详细探讨当子线程任务发生异常时,如何让主线程捕获到该异常并进行事务的回滚。下面将从多线程编程的基础知识、线程池的使用、异常捕获三个方面进行阐述。 一、多...
标题中提到的“Spring事务管理只对出现运行期异常进行回滚”这一特性是基于Java异常处理机制的。在Java中,异常分为两种类型:运行时异常(RuntimeException及其子类)和检查异常(CheckedException)。运行时异常是...
首先,Spring 默认只有在遇到未捕获的 `RuntimeException` 或其子类时才会触发事务回滚。这意味着,如果在业务代码中对异常进行了捕获并处理,而没有再抛出异常,那么事务将不会自动回滚。例如,在提供的代码实例中...
浅谈Spring中@Transactional事务回滚及示例 @Transactional是Spring Framework中的一种事务管理机制,用于管理数据库事务。它可以使得数据库操作更加安全和可靠。本文将详细介绍@Transactional的使用场景、checked...
事务回滚是事务处理中的关键部分,确保在出现错误或异常时,数据库能够恢复到事务开始之前的状态。 在升级到MongoDB 4.0之后,首先需要注意的是确保环境的兼容性。使用Homebrew升级MongoDB到4.0.0版本,同时更新`...
在Spring中,事务回滚规则基于异常类型。默认情况下,只有未检查异常(RuntimeException及其子类)会导致事务回滚,而检查异常(非RuntimeException)不会。这是因为未检查异常通常表示编程错误,而检查异常则通常...
使用 SpringBoot 注解方式处理事务回滚实现 在本文中,我们将介绍使用 SpringBoot 注解方式处理事务回滚实现的方法,并通过示例代码进行详细的讲解。本文对于学习 SpringBoot 的开发者或者工作中需要实现事务回滚的...
在Spring框架中,默认情况下,对非检查型异常和运行时异常进行事务回滚,而对检查型异常则不进行回滚操作。因此,在编程中,需要注意检查型异常和非检查型异常的区别,并采取相应的处理方法。 一、检查型异常和非...
此外,需要注意的是,只有当事务边界内的异常是未检查异常(继承自RuntimeException的异常)或者是`Error`时,Spring才会自动回滚事务。对于已检查异常(继承自Exception的非RuntimeException),除非显式声明`@...
1. RuntimeException回滚:SpringBoot默认情况下,只有RuntimeException及其子类的异常会导致事务回滚。 2. 手动回滚:使用TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();方法来手动回滚...
此外,Spring 还提供了事务回滚规则,允许基于异常类型或异常实例来决定是否回滚事务,增强了事务处理的灵活性。 Spring AOP 用于实现事务管理服务,它通过代理模式在方法调用前后插入事务处理代码,无需修改原有...
4. **回滚规则:**默认情况下,如果方法抛出未检查异常(继承自`RuntimeException`)或`Error`,Spring会自动回滚事务。你也可以自定义回滚规则,比如添加`@Transactional(noRollbackFor=SomeException.class)`来...
本文将深入探讨这个注解的工作原理、如何配置以及如何在遇到异常时触发事务回滚。 首先,`@Transactional`是Spring提供的一个编程式事务管理方式,它允许我们在方法上声明事务属性,如传播行为、隔离级别、读写模式...
2. **声明式事务管理**:这是Spring最常用的方式,通过在配置文件或者使用`@Transactional`注解来定义事务边界,使得事务管理与业务逻辑分离,降低了代码的耦合度。`@Transactional`注解可以应用于方法级别,表示该...