首先感谢网友的文章
Spring事务失效的2种情况

JDK动态代理给Spring事务埋下的坑

前提知识: 两个前提

1 注解使用 spring容器的事务管理注解
@org.springframework.transaction.annotation.Transactional

2.方法开启了事务注解之后,需要异常的触发,
如果在方法内部捕获了异常,即使你开启了事务,也是没法事务回滚的

错误的使用:下面这种捕获了异常 , saveEmployee 方法里面的即使有事务,也是不会回滚的

@Transactional() //开启事务,捕获了异常,没法触发,所以有注解也没作用
public void save(){// 捕获了异常,没法触发,所以有注解也没作用try {   // 捕获了异常,没法触发,所以有注解也没作用     this.saveEmployee();  }catch (Exception e){e.printStackTrace();}
}@Transactional()
public void saveEmployee(){Employee employee = new Employee();employee.setName("zhangsan");employee.setAge("26";employeeDao.save(employee);throw new RuntimeException();
}

写作背景:

我们平时在java开发中经常使用的是 Spring 的事务回滚,而且我们大多数情况下都是使用注解为主的,最近工作中,方法内部调用,事务没有起效,走了一些弯路,今天来总结一下.

方法内部调用是指: 同一个类,两个方法, 外层方法( 暂且叫 A 方法 )调用内层方法(B 方法)

使用默认的事务处理方式
  因为在java的设计中,它认为不继承RuntimeException的异常是”checkException”或普通异常,如IOException,这些异常在java语法中是要求强制处理的。
  对于这些普通异常,spring默认它们都已经处理,所以默认不回滚。
  可以添加rollbackfor=Exception.class来表示所有的Exception都回滚。

内部调用
  不带事务的方法调用该类中带事务的方法,不会回滚。因为spring的回滚是用过代理模式生成的,如果是一个不带事务的方法调用该类的带事务的方法,直接通过this.xxx()调用,而不生成代理事务,所以事务不起作用。常见解决方法,拆类。

内部调用没有发生我们期待中的事务回滚:**
  spring中在一个拥有事务的方法A中调用另一个会挂起事务并创建新事务的方法B,
  如果使用this调用这个方法B, 此时方法B抛出了一个异常,
  此时的方法B的事务会失效的。并不会回滚。**
  
代码如下:

@Service
public class EmployeeService {@Autowiredprivate EmployeeDao employeeDao;public void save(){try {        //此处this调用不会开启事务,数据会被保存this.saveEmployee();  }catch (Exception e){e.printStackTrace();}}@Transactional()public void saveEmployee(){Employee employee = new Employee();employee.setName("zhangsan");employee.setAge("26";employeeDao.save(employee);throw new RuntimeException();}
}

问题原因: JDK的动态代理
JDK的动态代理。只有被动态代理直接调用时才会产生事务。
在SpringIoC容器中返回的调用的对象是代理对象而不是真实的对象。
而这里的this是EmployeeService真实对象而不是代理对象。

解决办法:

方法1:
在方法A上开启事务,方法B不用事务或默认事务,
并在方法A的catch中throw new RuntimeException();
(在没指定rollbackFor时,默认回滚的异常为RuntimeException),这样使用的就是方法A的事务。(一定要throw new RuntimeException();否则异常被捕捉处理,同样不会回滚。)
如下:

@Transactional() //开启事务
public void save(){try {        this.saveEmployee();  }catch (Exception e){e.printStackTrace();throw new RuntimeException();}
}

方法2:
方法2、方法A上可以不开启事务,方法B上开启事务,并在方法A中将this调用改成动态代理调用(AopContext.currentProxy()),如下:

public void save(){try {        EmployeeService proxy =(EmployeeService) AopContext.currentProxy();proxy.saveEmployee();}catch (Exception e){e.printStackTrace();}
}

另外还需要注意: 使用动态代理时候记得,在启动类配置开启代理

需要在启动类配置开启代理配置上:

@EnableTransactionManagement
@EnableAspectJAutoProxy(exposeProxy = true)

@EnableTransactionManagement
@SpringBootApplication
@EnableFeignClients(basePackages={"com.***"})
@EnableEurekaClient
@MapperScan("com.***.production.order.dao.mapper")
@ComponentScan(basePackages={"com.***"})
// 暴露代理
@EnableAspectJAutoProxy(exposeProxy = true)
public class ProductionOrderJobApplication {protected final static Logger logger = LoggerFactory.getLogger( ProductionOrderJobApplication.class);public static void main(String[] args) {SpringApplication app = new SpringApplication( ProductionOrderJobApplication.class);app.setBannerMode(Banner.Mode.OFF);app.run(args);logger.info("ProductionOrderJobApplication is success!");}@Beanpublic RequestContextListener requestContextListener(){return new RequestContextListener();}}

补充一点: 拆类 的方法可以试试

最终解决方案: 拆类的方法

Spring事务失效 -方法内部调用相关推荐

  1. Spring事务总结(一) 内部调用事务失效、异常回滚

    Spring事务总结(一) 内部调用事务失效.异常回滚 参考文章: (1)Spring事务总结(一) 内部调用事务失效.异常回滚 (2)https://www.cnblogs.com/gss128/p ...

  2. Spring事务内方法调用自身事务

    Spring事务内方法调用自身事务 增强的三种方式 ServiceA.java文件: 查看Spring Tx的相关日志: 可以看到只创建了一个事物ServiceA.service方法的事务,但是cal ...

  3. 聊聊Spring事务失效的12种场景,太坑人了

    前言 对于从事java开发工作的同学来说,spring的事务肯定再熟悉不过了. 在某些业务场景下,如果一个请求中,需要同时写入多张表的数据.为了保证操作的原子性(要么同时成功,要么同时失败),避免数据 ...

  4. 每日一博 - 常见的Spring事务失效事务不回滚案例集锦

    文章目录 事务不生效 方法内部调用 修复方法一 : [新加一个Service方法] 修复方法二:[在该Service类中注入自己] 修复方法三:[通过AopContent类]<---- 推荐 访 ...

  5. 详细整理Spring事务失效的具体场景及解决方案

    实际项目开发中,如果涉及到多张表操作时,为了保证业务数据的一致性,大家一般都会采用事务机制:好多小伙伴可能只是简单了解一下,遇到事务失效的情况,便会无从下手,溪源此篇文章给大家整理了一下常见Sprin ...

  6. 面试官:Spring事务失效的场景有哪些?如何解决?

     作者:溪~源 blog.csdn.net/xuan_lu/article/details/107797505 实际项目开发中,如果涉及到多张表操作时,为了保证业务数据的一致性,大家一般都会采用事务机 ...

  7. 你否有遇到Spring事务失效,花费太多时间找bug

    作者:溪~源 来源:blog.csdn.net/xuan_lu/article/details/107797505 实际项目开发中,如果涉及到多张表操作时,为了保证业务数据的一致性,大家一般都会采用事 ...

  8. spring事务失效了? @Transactional不管用了 ?看看这些@Transation的坑

    spring事务失效了? @Transactional不管用了 ?看看这些@Transactional的坑 文章目录 spring事务失效了? @Transactional不管用了 ?看看这些@Tra ...

  9. 详解spring事务失效和回滚失败的场景

    详解spring事务失效和回滚失败的场景 详解spring事务失效和回滚失败的场景 前言 一 .事务不生效 1.访问权限问题 2. 方法用final修饰 3.方法的内部调用 3.1 新加一个Servi ...

最新文章

  1. 4-2-串的堆存储结构-串-第4章-《数据结构》课本源码-严蔚敏吴伟民版
  2. java选择哪款eclipse_写java程序用哪一个版的eclipse比较好
  3. jvm二:类加载,连接,初始化
  4. zk ui_高级ZK:异步UI更新和后台处理–第1部分
  5. html十css十javascript,html代码,css代码,JavaScript代码, | 重蔚自留地
  6. Fedora升级后Python虚拟环境中的pip报错
  7. redhat简单安装Samba,JDK环境,Tomcat,Oracle11G
  8. makefile obj文件路径_makefile中包含的文件的路径
  9. 深度技术 GHOSTXPSP3 快速装机 2013圣诞节专版
  10. android lame,Android 采用Lame编码器编码mp3文件
  11. 如何制定项目里程碑?
  12. PC 上安装Windows10系统到硬盘上ESP分区丢失,新建ESP分区修复引导ESP分区创建失败解决办法
  13. Servlet/Filter中的url-pattern
  14. 进击的“懒人经济”,快手又迎来一个万亿蓝海市场
  15. 【读 深入浅出数据分析】 一日一章 读书第三天 第三章-最优化:寻找最大值
  16. 1.学生党如何查找文献书籍
  17. 记一次git pull 错误
  18. 欧几里得变换(Euclidean transformation)详解
  19. 语法基础(三. 类,属性,方法,方法重载,方法重写,构造方法,访问修饰符)
  20. 去掉/隐藏 word的回车符

热门文章

  1. Spark GraphX算法 - Aggregate Messages (aggregateMessages)算法
  2. Idea 版本控制冲突解决
  3. css 商城 两列_css大法之使用伪元素实现超实用的图标库(附源码
  4. JavaScript(五)——错误处理
  5. 牛客练习赛50-C——tokitsukaze and Soldier
  6. linux mysql root用户密码_Linux下修改Mysql的用户(root)的密码
  7. Statement returned more than one row, where no more than one was expected
  8. Dubbo与Spring Cloud
  9. P2574 XOR的艺术
  10. solr索引创建流程