ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Springboot @Transactional 事务不回滚

2021-06-17 20:02:28  阅读:194  来源: 互联网

标签:事务 调用 Springboot Transactional 代理 AOP 不回 异常


一、异常捕获的原因

  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,Transactional,代理,AOP,不回,异常
来源: https://www.cnblogs.com/edda/p/14897014.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有