关于SpringBoot的异常回滚和事务的使用详解

 更新时间:2023年05月10日 10:01:25   作者:Archie_java  
这篇文章主要介绍了关于SpringBoot的异常回滚和事务的使用详解,Spring中 @Transactional 注解,默认情况下,只对抛出的RuntimeException 异常,才会事务回滚,需要的朋友可以参考下

Springboot中事务的使用:

1、启动类加上@EnableTransactionManagement注解,开启事务支持(其实默认是开启的)。

2、在使用事务的public(只有public支持事务)方法(或者类-相当于该类的所有public方法都使用)加上@Transactional注解。

在实际使用中一般是在service中使用@Transactional,那么对于controller->service流程中:

如果controller未开启事务,service中开始了事务,service成功执行,controller在之后的运行中出现异常(错误),不会自动回滚。

也就是说,只有在开启事务的方法中出现异常(默认只有非检测性异常才生效-RuntimeException )(错误-Error)才会自动回滚。

如果想要对抛出的任何异常都进行自动回滚(而不是只针对RuntimeException),只需要在使用@Transactional(rollbackFor = Exception.class)即可。

开启事务的方法中事务回滚的情况:

①未发现的异常,程序运行过程中自动抛出RuntimeException或者其子类,程序终止,自动回滚。

②使用TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();进行手动回滚。

③注意:如果在try-catch语句中对可能出现的异常(RuntimeException)进行了处理,没有再手动throw异常,spring认为该方法成功执行,不会进行回滚,此时需要调用②中方法进行手动回滚 (java 框架项目案例:www.fhadmin.org)

另外,如果try-catch语句在finally中进行了return操作,那么catch中手动抛出的异常也会被覆盖,同样不会自动回滚。

//不会自动回滚
try{
    throw new RuntimeException();
}catch(RuntimeException e){
    e.printStackTrace();
}finally{
}
//会自动回滚
try{
    throw new RuntimeException();
}catch(RuntimeException e){
    e.printStackTrace();
    throw new RuntimeException();
}finally{
}

Springboot @Transactional 事务不回滚

一、异常捕获的原因

  1. 这里Exception异常,他又分为运行时异常RuntimeException和非运行时异常
  2. 可查的异常(checked exceptions):Exception下除了RuntimeException外的异常
  3. 不可查的异常(unchecked exceptions):RuntimeException及其子类和错误(Error)
  4. 异常checked例外也回滚:在整个方法前加上 @Transactional(rollbackFor=Exception.class)
  5. 异常unchecked例外不回滚: @Transactional(notRollbackFor=RunTimeException.class)
  6. 如果异常被try{}catch{}了,事务就不回滚了,如果想让事务回滚必须再往外抛try{}catch{throw Exception}

二、数据库引擎不支持回滚(使用MYSQL就很可能是这个原因)

  1. Mysql数据库有两种引擎,注意要使用支持事务的引擎,比如innodb,如果是MyISAM,事务是不起作用的。
  2. 使用springboot的jpa自动创建库表的时候,默认使用MyISAM引擎,可以检查库表查看引擎。
  3. 修改配置:
spring:  
  jpa:
    hibernate:
      ddl-auto: update
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl #按字段名字建表
    show-sql: true
    database: mysql
    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect  #使用innodb引擎建表

三、发生了自调用情况

spring的数据库事务调用的实现原理是AOP,而AOP的原理是动态代理,在自调用的过程中,是类自身的调用,而不是代理对象去调用,那么不会产生AOP,没有AOP,意味着@Transactional不会被切面捕获,这样spring就不能把你的代码植入到约定的流程中,于是就产生了事务回滚失败。

解决方案:

1、将涉及到事务的处理都放入一个方法中,由其他类调用。

2、如果非要在本类中调用,那么需要在本类中生成本类的bean对象,由这个bean对象来调用,实现方式也有多种:

  • 自注入
  • 通过SpringContextHolder获取bean,即注入ApplicationContext,从ApplicationContext获取bean
  • 通过AopContext获取当前类的代理对象,注意此种方式需要开启expose-proxy=“true”,可通过注解开启@EnableAspectJAutoProxy(exposeProxy =true)

最后一种方式的伪代码:

@Service
public class OrderService {
  public void insert() {
    OrderService proxy = (OrderService) AopContext.currentProxy();
       proxy.insertOrder();
    }
    @Transactional
    public void insertOrder() {
        //SQL操作
       }
}

因为AopContext默认是不暴露当前代理类的,所以要@EnableAspectJAutoProxy(exposeProxy =true)或者<aop:aspectj-autoproxy expose-proxy=“true”/>:

四、补充:

在Spring 的AOP实现有两种代理方式:

  • Java动态代理 :通过反射生成一个实现了代理方法的匿名类来完成代理
  • cglib代理 :通过Asm修改字节码文件,生成一个子类来完成代理

Spring在项目中会根据被代理对象是否实现了接口来自动切换上述两种代理方式

所以private方法也不能实现事务

到此这篇关于关于SpringBoot的异常回滚和事务的使用详解的文章就介绍到这了,更多相关SpringBoot异常回滚和事务的使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java 线程池详解及实例代码

    Java 线程池详解及实例代码

    这篇文章主要介绍了Java 线程池的相关资料,并符实例代码,帮助大家学习参考,需要的朋友可以参考下
    2016-09-09
  • Java责任链设计模式

    Java责任链设计模式

    这篇文章主要介绍了Java责任链设计模式的相关资料,需要的朋友可以参考下
    2016-03-03
  • es创建索引和mapping的实例

    es创建索引和mapping的实例

    这篇文章主要介绍了es创建索引和mapping的实例,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • SpringMVC实现用户登录全过程

    SpringMVC实现用户登录全过程

    这篇文章主要介绍了SpringMVC实现用户登录全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-09-09
  • 利用stream sorted进行降序排序

    利用stream sorted进行降序排序

    这篇文章主要介绍了利用stream sorted进行降序排序,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-03-03
  • Java,C#使用二进制序列化、反序列化操作数据

    Java,C#使用二进制序列化、反序列化操作数据

    这篇文章主要介绍了Java,C#使用二进制序列化、反序列化操作数据的相关资料,需要的朋友可以参考下
    2014-10-10
  • 超全面的SpringBoot面试题含答案

    超全面的SpringBoot面试题含答案

    这篇文章主要收录了44道面试中经常被问的SpringBoot问题,不管你是正在求职的新手还是已经工作很久的高手,这篇关于SpringBoot的面试题总结一定会让你有新的理解,让我们一起来看看吧
    2023-03-03
  • Spring AOP日志框架实现过程图解

    Spring AOP日志框架实现过程图解

    这篇文章主要介绍了Spring AOP日志框架实现过程图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09
  • Java字节缓存流的构造方法之文件IO流

    Java字节缓存流的构造方法之文件IO流

    这篇文章主要介绍了Java字节缓存流的构造方法之文件IO流,同时也介绍了字符流中的一些相关的内容,并且通过大量的案例供大家理解。最后通过一些经典的案例帮助大家对前面所学的知识做了一个综合的应用,需要的朋友可以参考一下
    2022-04-04
  • Apache Commons Math3学习之数值积分实例代码

    Apache Commons Math3学习之数值积分实例代码

    这篇文章主要介绍了Apache Commons Math3学习之数值积分实例代码,涉及使用辛普森积分的例子,这里分享给大家,供需要的朋友参考。
    2017-10-10

最新评论