关于Spring中@Transactional事务回滚的注意事项

2023-05-30 0 3,125

目录

一、Spring 默认事务

Spring中 @Transactional 注解,默认情况下,只对抛出RuntimeException 异常,才会事务回滚。

如果事务的方法中抛出 unchecked异常(RuntimeException),事务会进行回滚( rollback);如果事务的方法中抛出是 checked异常(Exception),事务不会回滚。

也就是说,默认情况下, @Transactional 注解 只对抛出的 RuntimeException 异常和其子类异常 才有效,对 Exception 及 Exception 的子类异常无效。

伪代码说明

// @Transactional 默认就是 RuntimeException 有效,抛出 RuntimeException时,事务会回滚。
@Transactional     
public void methodName1() {
	//... 各种的业务逻辑省略	
	throw new RuntimeException(\"RuntimeException\");	
}
// @Transactional 默认就是 RuntimeException 有效,抛出 Exception 时,事务不会回滚。
@Transactional
public void methodName22() {
	//... 各种的业务逻辑省略
	throw new Exception(\"Exception\");
}
// @Transactional 指定回滚事务是 Exception时,遇到 RuntimeException 时,事务不会回滚
@Transactional( rollbackFor=Exception.class )
public  void methodName3() {
	//... 各种的业务逻辑省略
	throw new RuntimeException(\"RuntimeException\");
}
// @Transactional 指定回滚事务是 Exception时,遇到异常 Exception 时,事务会回滚,
@Transactional( rollbackFor=Exception.class ) 
public void methodName4() {
	//... 各种的业务逻辑省略
	throw new Exception(\"Exception\");
}

@Transactional 相当于 @Transactional(rollbackFor=RuntimeException.class) ,只对抛出的 RuntimeException 异常,才会事务回滚。

1.1、抛出 unchecked 和 checked 异常都回滚

如果希望无论抛出是 RuntimeException (unchecked ) ,还是 Exception (checked),事务都要回滚。

@Transactional( rollbackFor = {RuntimeException.class, Exception.class} )
public  void methodName5() {
	//... 业务省略
	if(){		
		throw new RuntimeException(\"RuntimeException\");
	}
	//... 业务省略
	if(){		
		throw new Exception(\"Exception\");
	}	
}

1.2、总结

  • Spring 中 @Transactional ,默认只对抛出的 RuntimeException 的出常,事务才会回滚。
  • 如果希望无论抛出是 RuntimeException ,还是 Exception,事务都要回滚,请使用如下配置。
@Transactional(rollbackFor={RuntimeException.class, Exception.class})

二、使用 Spring中 @Transactional 注解的注意事项

  1. @Transactional 注解只能应用到 public 的方法上。 如果你在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不会报错, 但是这个被注解的方法将不会展示已配置的事务设置。
  2. 配置 proxy-target-class 是指定基于接口的,还是基于类的代理被创建。如果 proxy-target-class = false (默认值),那么标准的JDK基于接口的代理。 如果 proxy-target-class = true,那么基于类的代理将起作用(需要CGLIB库)。
  3. @Transactional 注解 加在 具体方法(或类)上面 ,而不是接口上面。 在接口上使用 @Transactional 注解,只能当你设置了基于接口的代理时它才生效。 因为注解是 不能继承 的,这就意味着如果正在使用基于类的代理时,那么事务的设置将不能被基于类的代理所识别,而且对象也将不会被事务代理所包装。
  4. @Transactional 的事务是通过基于接口的,或者是基于类的代理才能被创建。在同一个类中一个方法调用另一个有事务注解的方法,事务是不会起作用的。

这条能理解吗 ?下面是解释说明。

伪代码说明

@Serive
public class XxxService{	
	public void aa(){
		//业务...
		bb()
		//业务...
	}
	@Transactional
	public void bb(){
		//业务...
	}
}
@Controller
public class XxxController(){
	@Autowired
	XxxService xxxService;
	@RquestMapping(\"/hello\")
	public void hello(){
		xxxService.aa();
	}
}
XxxController.hello() 调用 XxxService 时,没有开启事务,在 aa()、 bb()发生的RuntimerException 不会事务回滚。
分析说明:
(1)因为 aa() 没有 @Transactional 注解,因此 XxxController 调用 XxxService 时 ,没有开启事务;
(2)aa()中调有 bb() 只是方法的调用(代码片段的调用)。类似于Thread中,开启线程是通过start()方法,而不是直接调用run()方法。

spring 在扫描bean的时候会扫描方法上是否包含@Transactional 事务注解,如果包含,则 spring会为这个bean动态地生成一个子类(即代理类,proxy),代理类是继承原来那个bean 。

当这个有事务注解的方法被调用的时候,实际上是由代理类来调用的,代理类在调用之前就会开启事务(transaction) 。

但是,如果先调用一个没有事务的方法,然通这个方法再去有事务,由于该方法的调用并没有通过代理类,而是直接通过原来的那个bean,所以就不会启动transaction,我们看到的现象就是 @Transactional 注解无效。

总结: 同一个类中,一个没有事务的方法A,去调用另一个有事务的方法B时,因为是直接调用,而不是调用的代理类,所以事务不起用的。

资源下载此资源下载价格为1小猪币,终身VIP免费,请先
由于本站资源来源于互联网,以研究交流为目的,所有仅供大家参考、学习,不存在任何商业目的与商业用途,如资源存在BUG以及其他任何问题,请自行解决,本站不提供技术服务! 由于资源为虚拟可复制性,下载后不予退积分和退款,谢谢您的支持!如遇到失效或错误的下载链接请联系客服QQ:442469558

:本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可, 转载请附上原文出处链接。
1、本站提供的源码不保证资源的完整性以及安全性,不附带任何技术服务!
2、本站提供的模板、软件工具等其他资源,均不包含技术服务,请大家谅解!
3、本站提供的资源仅供下载者参考学习,请勿用于任何商业用途,请24小时内删除!
4、如需商用,请购买正版,由于未及时购买正版发生的侵权行为,与本站无关。
5、本站部分资源存放于百度网盘或其他网盘中,请提前注册好百度网盘账号,下载安装百度网盘客户端或其他网盘客户端进行下载;
6、本站部分资源文件是经压缩后的,请下载后安装解压软件,推荐使用WinRAR和7-Zip解压软件。
7、如果本站提供的资源侵犯到了您的权益,请邮件联系: 442469558@qq.com 进行处理!

猪小侠源码-最新源码下载平台 Java教程 关于Spring中@Transactional事务回滚的注意事项 http://www.20zxx.cn/763222/xuexijiaocheng/javajc.html

猪小侠源码,优质资源分享网

常见问题
  • 本站所有资源版权均属于原作者所有,均只能用于参考学习,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担
查看详情
  • 最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,建议提前注册好百度网盘账号,使用百度网盘客户端下载
查看详情

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务