【小家java】Spring事务不生效的原因大解读

简介: 【小家java】Spring事务不生效的原因大解读

相关阅读


【小家java】java5新特性(简述十大新特性) 重要一跃

【小家java】java6新特性(简述十大新特性) 鸡肋升级

【小家java】java7新特性(简述八大新特性) 不温不火

【小家java】java8新特性(简述十大新特性) 饱受赞誉

【小家java】java9新特性(简述十大新特性) 褒贬不一

【小家java】java10新特性(简述十大新特性) 小步迭代

【小家java】java11新特性(简述八大新特性) 首个重磅LTS版本

每篇一句


你又多特殊,你就有多值钱。反过来依然成立:你有多值钱,你就有多特殊


1、概述


事务在后端开发中无处不在,是数据一致性的最基本保证。在Spring中可以通过对方法进行事务的配置,而不是像原来通过手动写代码的方式实现事务的操作,这在很大程度上减少了开发的难度。因此我们在使用spring事务的时候,门槛变得异常的低,小学生水平就能很好的管理好事务,但是同学们或多或少都遇见过一些事务不生效的难题,为啥呢?本文就针对于此来做一些具体举例分析,尽量做到全覆盖


2、栗子


    Spring团队建议在具体的类(或类的方法)上使用 @Transactional 注解,而不要使用在类所要实现的任何接口上。在接口上使用 @Transactional 注解,只能当你设置了基于接口的代理时它才生效。因为注解是 不能继承 的,这就意味着如果正在使用基于类的代理时,那么事务的设置将不能被基于类的代理所识别,而且对象也将不会被事务代理所包装。


**原因一:**是否是数据库引擎设置不对造成的。比如我们最常用的mysql,引擎MyISAM,是不支持事务操作的。需要改成InnoDB才能支持


**原因二:**入口的方法必须是public,否则事务不起作用(这一点由Spring的AOP特性决定的,理论上而言,不public也能切入,但spring可能是觉得private自己用的方法,应该自己控制,不应该用事务切进去吧)。另外private 方法, final 方法 和 static 方法不能添加事务,加了也不生效


**原因三:Spring的事务管理默认只对出现运行期异常(java.lang.RuntimeException及其子类)进行回滚(至于为什么spring要这么设计:因为spring认为Checked的异常属于业务的,coder需要给出解决方案而不应该直接扔该框架)


原因四:@EnableTransactionManagement // 启注解事务管理,等同于xml配置方式的 <tx:annotation-driven />


备注:本系列所有博文的讨论都针对于springboot而不再对spring做说明。

@EnableTransactionManagement 在springboot1.4以后可以不写。框架在初始化的时候已经默认给我们注入了两个事务管理器的Bean(JDBC的DataSourceTransactionManager和JPA的JpaTransactionManager ),其实这就包含了我们最常用的Mybatis和Hibeanate了。当然如果不是AutoConfig的而是自己自定义的,请使用该注解开启事务


**原因五:**请确认你的类是否被代理了(因为spring的事务实现原理为AOP,只有通过代理对象调用方法才能被拦截,事务才能生效)


**原因六:**请确保你的业务和事务入口在同一个线程里,否则事务也是不生效的,比如下面代码事务不生效:

@Transactional
@Override
public void save(User user1, User user2) {
    new Thread(() -> {
          saveError(user1, user2);
          System.out.println(1 / 0);
    }).start();
}


**原因六:**也是我最想要去讲的一个原因:service方法中调用本类中的另一个方法,事务没有生效。这里我把当初保存的几张对比图贡献给大家参考,一目了然:


图一:事务不生效:.@Transactional的事务开启 ,或者是基于接口的 或者是基于类的代理被创建。所以在同一个类中一个无事务的方法调用另一个有事务的方法,事务是不会起作用的(这就是业界老问题:类内部方法调用事务不生效的问题原因)。


image.png


图二:事务生效


image.png


图三:事务生效


image.png


图四:事务生效


image.png


图五:事务生效(稍微解释一下,这里虽然是方法内部调用,但是事务切入了addInfo方法,所以即使内部抛出异常,也是可以生效的。当年我竟然惊讶,看来还是太年轻,哈哈)


image.png


图六:事务不生效(准确的说这叫没有事务)


image.png


图七:事务生效。这里必须说几句:这是我们解决方法内部调用事务不生效的最常用方法之一:内部维护一个注入自己的Bean,然后使用这个属性来调用方法。其实还有一种方法,那就是利用Aop上下文来获取代理对象(((TestService)AopContext.currentProxy()).create(); ),然后通过代理对象来调用。这里需要注意:Aop上下文spring默认是关闭的,需要手动开启


image.png


3、使用场景



事务的使用场景无需多言,但怎么正确的使用好事务却有很多学问而且有很深的学问。本文只在应用层面帮大家汇总一下事务不生效的原因,其实更有效的理解必须结合springboot的源码进行讨论,这个在后续博文中会深入源码级别分析,各位看官可持续关注

4、最后


任何一件事情本身的复杂度是不会改变的,只是从一个地方转移到了另外一个地方。spring的事务管理就是这么一把双刃剑,它封闭了太对对开发者的实现,所以对开发者十分的友好。但如果出了问题,解决问题和理解问题的本质原因的复杂度将大幅提升。但是,作为新互联网时代,面向元数据编程肯定是一种趋势,而spring就是很好的先驱者


相关文章
|
3月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
131 2
|
16天前
|
存储 NoSQL Java
使用Java和Spring Data构建数据访问层
本文介绍了如何使用 Java 和 Spring Data 构建数据访问层的完整过程。通过创建实体类、存储库接口、服务类和控制器类,实现了对数据库的基本操作。这种方法不仅简化了数据访问层的开发,还提高了代码的可维护性和可读性。通过合理使用 Spring Data 提供的功能,可以大幅提升开发效率。
60 21
|
6天前
|
网络协议 Java Shell
java spring 项目若依框架启动失败,启动不了服务提示端口8080占用escription: Web server failed to start. Port 8080 was already in use. Action: Identify and stop the process that’s listening on port 8080 or configure this application to listen on another port-优雅草卓伊凡解决方案
java spring 项目若依框架启动失败,启动不了服务提示端口8080占用escription: Web server failed to start. Port 8080 was already in use. Action: Identify and stop the process that’s listening on port 8080 or configure this application to listen on another port-优雅草卓伊凡解决方案
29 7
|
1月前
|
Java Spring
Java Spring Boot监听事件和处理事件
通过上述步骤,我们可以在Java Spring Boot应用中实现事件的发布和监听。事件驱动模型可以帮助我们实现组件间的松耦合,提升系统的可维护性和可扩展性。无论是处理业务逻辑还是系统事件,Spring Boot的事件机制都提供了强大的支持和灵活性。希望本文能为您的开发工作提供实用的指导和帮助。
100 15
|
1月前
|
监控 JavaScript 数据可视化
建筑施工一体化信息管理平台源码,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
智慧工地云平台是专为建筑施工领域打造的一体化信息管理平台,利用大数据、云计算、物联网等技术,实现施工区域各系统数据汇总与可视化管理。平台涵盖人员、设备、物料、环境等关键因素的实时监控与数据分析,提供远程指挥、决策支持等功能,提升工作效率,促进产业信息化发展。系统由PC端、APP移动端及项目、监管、数据屏三大平台组成,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
|
1月前
|
SQL Java 关系型数据库
【SpringFramework】Spring事务
本文简述Spring中数据库及事务相关衍伸知识点。
50 9
|
2月前
|
Java 开发者 Spring
理解和解决Spring框架中的事务自调用问题
事务自调用问题是由于 Spring AOP 代理机制引起的,当方法在同一个类内部自调用时,事务注解将失效。通过使用代理对象调用、将事务逻辑分离到不同类中或使用 AspectJ 模式,可以有效解决这一问题。理解和解决这一问题,对于保证 Spring 应用中的事务管理正确性至关重要。掌握这些技巧,可以提高开发效率和代码的健壮性。
127 13
|
2月前
|
Java 开发者 微服务
Spring Boot 入门:简化 Java Web 开发的强大工具
Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级别的基于Spring框架的应用程序。它旨在简化Spring应用的初始搭建以及开发过程。
97 6
Spring Boot 入门:简化 Java Web 开发的强大工具
|
2月前
|
缓存 安全 Java
Spring高手之路26——全方位掌握事务监听器
本文深入探讨了Spring事务监听器的设计与实现,包括通过TransactionSynchronization接口和@TransactionalEventListener注解实现事务监听器的方法,并通过实例详细展示了如何在事务生命周期的不同阶段执行自定义逻辑,提供了实际应用场景中的最佳实践。
75 2
Spring高手之路26——全方位掌握事务监听器
|
2月前
|
Java 关系型数据库 数据库
京东面试:聊聊Spring事务?Spring事务的10种失效场景?加入型传播和嵌套型传播有什么区别?
45岁老架构师尼恩分享了Spring事务的核心知识点,包括事务的两种管理方式(编程式和声明式)、@Transactional注解的五大属性(transactionManager、propagation、isolation、timeout、readOnly、rollbackFor)、事务的七种传播行为、事务隔离级别及其与数据库隔离级别的关系,以及Spring事务的10种失效场景。尼恩还强调了面试中如何给出高质量答案,推荐阅读《尼恩Java面试宝典PDF》以提升面试表现。更多技术资料可在公众号【技术自由圈】获取。

热门文章

最新文章