问题描述:

我们在用Spring框架开发Web项目过程中,经常需要用同一个service中的一个方法调用另一个方法,如果此时调用方没有添加事务注解@Transactional,而在被调用方添加事务注解@Transactional,当被调用方法中出现异常,这时候会发现事务并没有回滚,事务注解@Transactional没有起作用。

分析原因:

我们知道Spring中事务管理是使用AOP代理技术实现的,目标对象自身并没有事务管理功能的,而是通过代理对象动态增强功能对事务进行增强的。因此当我们在同一个service类中通过一个方法调用另一个方法时,是通过目标对象this对象调用的,目标对象自身并没有事务管理功能,因此事务不能生效。

下面我们用代码演示下:

 public class UserService{...public User getUserByName(String name) {return userDao.getUserByName(name);}...

如果配置了事务, 就相当于又创建了一个代理类:

  public class UserServiceProxy extends UserService{private UserService userService;...public User getUserByName(String name){User user = null;try{// 在这里开启事务user = userService.getUserByName(name);// 在这里提交事务}catch(Exception e){// 在这里回滚事务// 这块应该需要向外抛异常, 否则我们就无法获取异常信息了. // 至于方法声明没有添加异常声明, 是因为覆写方法, 异常必须和父类声明的异常"兼容". // 这块应该是利用的java虚拟机并不区分普通异常和运行时异常的特点.throw e;}return user;}...}
 @Autowiredprivate UserService userService;    // 这里spring注入的实际上是UserServiceProxy的对象private void test(){// 由于userService是UserServiceProxy的对象, 所以拥有了事务管理的能力userService.getUserByName("aa");}

Spring事务失效的其他原因

通过对Spring事务代理模式的分析,我们不难发现Spring事务失效的原因有以下几种情况:

1.private、static、final的使用

解决方法:不在类和方法上使用此类关键字

2.通过this.xxx(调用当前类的方法)

使用xml配置方式暴露代理对象.然后在service中通过代理对象AopContext.currentProxy()去调用方法。

xml配置

<aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true"/>
 1 @Service2 public class HelloWorldServiceImpl implements HelloWorldService {3     @Autowired4     private BlogRepository blogRepository;5 6     @Override7     public void a(BlogEntity blogEntity) throws Exception {8         ((HelloWorldService) AopContext.currentProxy()).b(blogEntity);9     }
10
11     @Transactional(rollbackFor = Exception.class)
12     @Override
13     public void b(BlogEntity blogEntity) throws Exception {
14         blogRepository.save(blogEntity);
15         throw new Exception("错误");
16     }
17 }

3.使用默认的事务处理方式

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

4.线程Thread中声明式事务不起作用

 1 @Override2     public void run() {3         DefaultTransactionDefinition def = new DefaultTransactionDefinition();4         def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);5         PlatformTransactionManager txManager = ContextLoader.getCurrentWebApplicationContext().getBean(PlatformTransactionManager.class);6         TransactionStatus status = txManager.getTransaction(def);7         try {8                testDao.save(entity);9                txManager.commit(status); // 提交事务
10             } catch (Exception e) {
11                 System.out.println("异常信息:" + e.toString());
12                 txManager.rollback(status); // 回滚事务
13             }
14     }

从上面代码可以看出,我们的解决方案是使用了编程式事务。

5.配置的事务与扫描的service不在同一个容器

在spring-framework-reference.pdf文档中有这样一段话:

<tx:annotation-driven/> only looks for @Transactional on beans in the same application context it is defined in. This means that, if you put <tx:annotation-driven/> in a WebApplicationContext for a DispatcherServlet, it only checks for @Transactional beans in your controllers, and not your services.

这句话的意思是,<tx:annoation-driven/>只会查找和它在相同的应用上下文件中定义的bean上面的@Transactional注解,如果你把它放在Dispatcher的应用上下文中,它只检查控制器上的@Transactional注解,而不是你services上的@Transactional注解。

如果将事务配置定义在Spring MVC的应用上下文(*-servlet.xml)中,在Controller上的@Transactional注解是可以起作用的。而services上的@Transactional注解将不起作用。

详情可见:https://www.cnblogs.com/xiaojiesir/p/11058541.html

6.方法配置的事务传播行为有问题

被调用方法的事务传播行为设置为PROPAGATION_REQUIRES_NEW,导致产生两个独立的事务,外围方法抛出异常只回滚和外围方法同一事务的方法。

详情可见:https://segmentfault.com/a/1190000013341344

●史上最强Tomcat8性能优化

●阿里巴巴为什么能抗住90秒100亿?--服务端高并发分布式架构演进之路

●B2B电商平台--ChinaPay银联电子支付功能

●学会Zookeeper分布式锁,让面试官对你刮目相看

●SpringCloud电商秒杀微服务-Redisson分布式锁方案

查看更多好文,进入公众号--撩我--往期精彩

一只 有深度 有灵魂 的公众号0.0

Spring中同一个service中方法相互调用事务不生效问题解决方案相关推荐

  1. Spring中同一个service类中方法相互调用事务不生效问题解决方案

    此处的this指向目标对象,因此调用this.b()将不会执行b事务切面,即不会执行事务增强,因此b方法的事务定义@Transactional(propagation = Propagation.RE ...

  2. Spring中同一个类中方法调用事务不生效,非事务方法调用事务方式事务不生效

    我们假定在SerivceXXX中有两个方法: serviceA 非事务方法 serviceB事务方法 如果serviceA中方法定义类似如下: public void serviceA(){..... ...

  3. Spring中如Service有多个实现类,它怎么知道该注入哪个ServiceImpl类?

     作者:zoe_java cnblogs.com/zoe-java/p/11530888.html 方法一: Controller中注入service的时候使用@Autowired自动注入,@Qual ...

  4. 同一个controller中同一个service不同的方法调用怎么有的会为null

    今天疯狂给测试写bug的时候,发现我同一个controller中不同的方法调用同一个service竟然有的方法会为null.当时就很奇怪了,不过仔细看了下,应该是我手滑public写成private了 ...

  5. Spring中使用atomikos+druid实现经典分布式事务

    经典分布式事务,是相对互联网中的柔性分布式事务而言,其特性为ACID原则,包括原子性(Atomictiy).一致性(Consistency).隔离性(Isolation).持久性(Durabilit) ...

  6. Shiro与Spring集成时,Shiro权限注解@RequiresRoles等不生效的解决方案

    2019独角兽企业重金招聘Python工程师标准>>> Shiro与Spring集成时,Shiro权限注解@RequiresRoles等不生效, 这个问题着实整了好久,网上各种解决方 ...

  7. Java中Spring中的方法加上try catch后事务管理器失效无法回滚的情况

    beab.xml配置 <bean id="dataSource" class="org.springframework.jdbc.datasource.Driver ...

  8. Spring中的@ Component,@ Repository和@Service批注有什么区别?

    @Repository @Component , @Repository和@Service批注可以在Spring中互换使用吗,或者除了充当注解设备外,它们还提供任何特定功能吗? 换句话说,如果我有一个 ...

  9. Spring中的事务控制

    Chapter 1. Spring中的事务控制(Transacion Management with Spring) Table of Contents 1.1. 有关事务(Transaction)的 ...

最新文章

  1. Java 多线程(四)—— 单例模式
  2. 如何判断一个程序是 32bit 还是 64bit ?
  3. mongodb 创建数据库权限账号,增删改查(基本操作)
  4. 关于Unity中OnGUI()的简单使用
  5. 探索 SharePoint 2013 Search功能
  6. python类方法和静态方法_Python 中的方法、静态方法(static method)和类方法(class method)...
  7. 配置单交换机VLAN划分
  8. ghost之后仍然中病毒----与病毒的斗争
  9. LeetCode之数组中的最长山脉
  10. 网页游戏防外挂策略。
  11. DSPE-PEG-cRGD,磷脂-聚乙二醇-环肽RGD,靶向穿膜肽RGD环肽供应
  12. JAVA Swing主题 简洁扁平化苹果风格主题
  13. Android 开源1:获取并解析网页信息(Jsoup)
  14. 吾爱破解热榜:45k 的小工具让 Windows 升级成「全面屏」!
  15. 百度网盘下载显示系统限制,无法下载解决
  16. STM32(六)——串口通信原理
  17. 谈谈我对于项目管理的认识!
  18. 三维建筑形式的生成 Graph Convolutional Network
  19. windows如何使用vnc,只需5步轻松掌握windows下使用vnc
  20. VMware workstation 6.5.1 下载

热门文章

  1. python学习之地址簿程序
  2. 【数据结构】线段树的扩展与应用
  3. Windows11原版镜像
  4. 办理测绘资质所需流程以及材料(2022最新)
  5. Android如何隐藏应用程序的图标
  6. 正能量:前思科中国区总裁林正刚先生以自己35年职业经历和心得
  7. WSO2服务端部署常见的问题以及解决方案
  8. 【一库】妙啊!这个库组织npm脚本简直爆炸!
  9. 控制BLDC资料汇总
  10. KVM虚拟化,超详细