@test注解 无法运行_99%的Java程序员都不知道的Spring中的@Transactional注解的坑

在我们开发中很多时候都要用到事务,例如转账、充值等等的操作,这些我就不多BB了,于是很多人就选择最简单的方式@Transactional注解,但是你真的测试过事务异常的时候会回滚吗?等生产环境遇到了在来查找原因那就晚了,下面就说一下该注解的一下坑吧。
Transactional常见的几种失效原因

  • 没有配置事务管理器。配置方式如下:
  • 同一个类中,?一个未标注@Transactional的方法去调用标有@Transactional的方法,?事务会失效。
  • 该注解只能应用到?public?可见度的方法上。?如果应用在protected、private或者?package可见度的方法上,也不会报错,但是事务设置不会起作用。
  • 数据库引擎本身不支持事务,比如说MySQL数据库中的myisam,事务是不起作用的。
  • Spring只会对unchecked异常进行事务回滚;如果是checked异常则不回滚。

那什么是checked异常,什么是unchecked异常?我们把派生于Error或者RuntimeException的异常称为unchecked异常,所有其他的异常成为checked异常。什么又是RuntimeException呢,用《Effective Java》上的一句话来说吧。
Use checked exceptions for recoverable conditions and runtime exceptions for programming errors (Item 58 in 2nd edition)
从这句话中我们可以简单引申一下,也就是说,如果出现了RuntimeException,就一定是程序员自身的问题。比如说,数组下标越界和访问空指针异常等等,只要你稍加留心这些异常都是在编码阶段可以避免的异常。
针对最后一种情况,我们简单模拟一下吧,前期的准备工作这里就跳过了,直接开始我们今天的测试。测试之前数据库中的emp表只有一条数据信息。

v2-3c40829a650f96ab57be6975d78f8601_b.jpg


unchecked异常事务回滚验证
现在我们先模拟正常情况(RuntimeException, 我们使用最简单的数组越界异常。) 废话不多说,直接上代码:
@Test @Transactional public void test(){ Emp emp1 = new Emp(); emp1.setEmpname("测试二"); emp1.setEmail("test02@qq.com"); empService.insertEmp(emp1); /** * 模拟RuntimeException异常回滚 * */ int[] arr = {0}; System.out.println(arr[1]);//越界 Emp emp2 = new Emp(); emp2.setEmpname("测试三"); emp2.setEmail("test03@qq.com"); empService.insertEmp(emp1); } 复制代码
运行之后效果截图:

v2-2594255591d3d6bd4aaa07545ae2c6f1_b.jpg

程序运行之后,我们看下数据库的数据情况:

v2-50844ae1c5fd0c9e8ce24e077914a9e7_b.jpg

代码运行之后,由于有RuntimeException异常抛出,所以事务回滚了,这两条数据都没保存成功。
checked异常事务回滚验证
接下来模拟checked异常事务是否回滚问题,我们强制抛出一个FileNotFoundException异常。 ?? 同样的,这里粘贴一下测试用的代码:
@Test @Transactional public void test() throws Exception{ Emp emp1 = new Emp(); emp1.setEmpname("测试四"); emp1.setEmail("test04@qq.com"); empService.insertEmp(emp1); /** * 文件一定不存在 * */ FileInputStream file = new FileInputStream("C:UserspokemonDocumentsabc.txt"); Emp emp2 = new Emp(); emp2.setEmpname("测试五"); emp2.setEmail("test05@qq.com"); empService.insertEmp(emp1); } 复制代码
报错情况:

v2-55da16b5905c68c9455048f6701714c5_b.jpg


程序运行之后,我们看下数据库的数据情况:

v2-5d2435dabf437941a0677b2e8263e1b5_b.jpg


从上面的截图可以看出,事务并没有回滚,empname是“测试四”的这条数据被写入数据库了。
等等,这种情况我们无法预料,那应该怎么办?总不能坐以待毙吧。
解决方案
这样添加事务@Transactional(rollbackOn = Exception.class), 不管检查异常还是非检查异常都会回滚。以上就是关于@Transactional注解事务的坑以及解决方案,如果感觉对你有用,算我没白忙活。

如果你对编程感兴趣或者想往编程方向发展,可以关注微信公众号【筑梦编程】,大家一起交流讨论!小编也会每天定时更新既有趣又有用的编程知识!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值