浅谈Spring中的事务回滚详解编程语言
2023-06-13 09:20:44 时间
使用Spring管理事务过程中,碰到过一些坑,因此也稍微总结一下,方便后续查阅。
1.代码中事务控制的3种方式
编程式事务:就是直接在代码里手动开启事务,手动提交,手动回滚。优点就是可以灵活控制,缺点就是太麻烦了,太多重复的代码了。 声明式事务:就是使用SpringAop配置事务,这种方式大大的简化了编码。需要注意的是切入点表达式一定要写正确。 注解事务:直接在Service层的方法上面加上@Transactional注解,个人比较喜欢用这种方式。
在工作中,看过别人写的代码出现了事务不回滚的现象。当然,事务不回滚的都是采用的声明式事务或者是注解事务;编程式事务都是自己写代码手动回滚的,因此是不会出现不回滚的现象。
声明式
事务和注解事务回滚的原理:当被切面切中或者是加了注解的方法中抛出了RuntimeException异常时,Spring会进行事务回滚。默认
情况下是
捕获到方法的
RuntimeException
异常
,也就是说抛出只要属于运行时的异常(即
RuntimeException及其子类
)都能回滚;但当抛出一个不属于运行时异常时,事务是不会回滚的。
(1)声明式事务配置切入点表达式写错了,没切中Service中的方法 (2)Service方法中,把异常给try catch了,但catch里面只是打印了异常信息,没有手动抛出RuntimeException异常 (3)Service方法中,抛出的异常不属于运行时异常(如IO异常),因为Spring默认情况下是捕获到运行时异常就回滚
正常情况下,按照正确的编码是不会出现事务回滚失败的。下面说几点保证事务能回滚的方法
(1)如果采用编程式事务,一定要确保切入点表达式书写正确 (2)如果Service层会抛出不属于运行时异常也要能回滚,那么可以将Spring默认的回滚时的异常修改为Exception,这样就可以保证碰到什么异常都可以回滚。具体的设置方式也说下:
(3)只有非只读事务才能回滚的,只读事务是不会回滚的 (4)如果在Service层用了try catch,在catch里面再抛出一个 RuntimeException异常,这样出了异常才会回滚 (5)如果你不喜欢(4)的方式,你还可以直接在catch后面写一句回滚代码(TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); )来实现回滚,这样的话,就可以在抛异常后也能return 返回值;比较适合需要拿到Service层的返回值的场景。具体的用法可以参见考下面的伪代码
编程式事务:就是直接在代码里手动开启事务,手动提交,手动回滚。优点就是可以灵活控制,缺点就是太麻烦了,太多重复的代码了。 声明式事务:就是使用SpringAop配置事务,这种方式大大的简化了编码。需要注意的是切入点表达式一定要写正确。 注解事务:直接在Service层的方法上面加上@Transactional注解,个人比较喜欢用这种方式。
在工作中,看过别人写的代码出现了事务不回滚的现象。当然,事务不回滚的都是采用的声明式事务或者是注解事务;编程式事务都是自己写代码手动回滚的,因此是不会出现不回滚的现象。
声明式
事务和注解事务回滚的原理:当被切面切中或者是加了注解的方法中抛出了RuntimeException异常时,Spring会进行事务回滚。默认
情况下是
捕获到方法的
RuntimeException
异常
,也就是说抛出只要属于运行时的异常(即
RuntimeException及其子类
)都能回滚;但当抛出一个不属于运行时异常时,事务是不会回滚的。
(1)声明式事务配置切入点表达式写错了,没切中Service中的方法 (2)Service方法中,把异常给try catch了,但catch里面只是打印了异常信息,没有手动抛出RuntimeException异常 (3)Service方法中,抛出的异常不属于运行时异常(如IO异常),因为Spring默认情况下是捕获到运行时异常就回滚
正常情况下,按照正确的编码是不会出现事务回滚失败的。下面说几点保证事务能回滚的方法
(1)如果采用编程式事务,一定要确保切入点表达式书写正确 (2)如果Service层会抛出不属于运行时异常也要能回滚,那么可以将Spring默认的回滚时的异常修改为Exception,这样就可以保证碰到什么异常都可以回滚。具体的设置方式也说下:
tx:method name="update*" propagation="REQUIRED" rollback-for="java.lang.Exception"/
tx:method name="update*" propagation="REQUIRED" rollback-for="java.lang.Exception"/
(3)只有非只读事务才能回滚的,只读事务是不会回滚的 (4)如果在Service层用了try catch,在catch里面再抛出一个 RuntimeException异常,这样出了异常才会回滚 (5)如果你不喜欢(4)的方式,你还可以直接在catch后面写一句回滚代码(TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); )来实现回滚,这样的话,就可以在抛异常后也能return 返回值;比较适合需要拿到Service层的返回值的场景。具体的用法可以参见考下面的伪代码
/** TransactionAspectSupport手动回滚事务:*/ @Transactional(rollbackFor = { Exception.class }) public boolean test() { try { doDbSomeThing(); } catch (Exception e) { e.printStackTrace(); //就是这一句了, 加上之后抛了异常就能回滚(有这句代码就不需要再手动抛出运行时异常了) TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); return false; return true; }
@Transactional(rollbackFor = { Exception.class })
//就是这一句了, 加上之后抛了异常就能回滚(有这句代码就不需要再手动抛出运行时异常了)
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
相关文章
- spring容器初始化过程总结_java构造方法初始化
- spring boot自动配置原理面试题_Spring boot面试
- 简单介绍一下spring bean的生命周期_Spring bean的生命周期
- 聊聊Spring事务控制策略以及@Transactional失效问题避坑
- Spring事务隔离级别与数据库隔离级别不一致时,该以谁为准?
- 创建Spring Boot应用
- 在Spring AOP切面中启用新事务
- 分布式事务atomikos的原理_spring分布式事务
- spring boot整合shiro_Spring框架介绍及使用
- 8-Spring事务控制
- Spring常用事务传播特性
- java 配置事务回滚_Spring@Transactional事务回滚
- 关于spring事务你需要知道的知识点
- Spring中的事务传播行为有哪些?
- Spring事务失效场景
- spring boot支持https请求(建议收藏)
- Spring MVC拦截器(Interceptor)
- Spring MVC和Struts2的区别
- 深入理解 Spring 事务原理详解编程语言
- spring的AOP(四)—-Spring AOP 编程(Advisor)详解编程语言
- Spring事务详解编程语言
- Spring事务异常回滚,捕获异常不抛出就不会回滚详解编程语言
- 代码抛出异常后进行事务回滚的两种方式(Spring @Transactional注解)详解编程语言
- Spring Boot 2.x :通过 spring-boot-starter-hbase 集成 HBase