@Transactional需要注意的问题

失效问题:

最近写的项目中需要一个service中的部分事务执行完就被commit,但是部分service需要失败回滚。因此写在一个大的service中并且加上@Transactional显然是无法满足需求的。
因此这是需要把原先的一个service服务拆分,如原先的serviceA被拆分成serviceA和ServiceB,并且在ServiceB上打@Transactional注解,而serviceA未打注解。
整体执行流程是由controller调用serviceA,再经serviceA调用serviceB。但是在执行过程发现serviceB中的事务语句在执行后就会被立马提交,事务控制未生效。
翻阅资料有的说因为context:component-scan重复加载导致失效,但是sprintg配置中扫描service的包无重复。于是抱着试试的心态在serviceA上继续添加@Transactional注解,返现这是serviceB的事务生效。
也就是说带事务注解的serviceA被其他service调用时,如果想要生效,最外层的也得加上@Transactional注解。
 

发生异常无法回滚:

紧接着上个问题说,serviceB中的事务生效后,在执行遇到异常时,捕获并且抛出自定的异常InvalidException extends Exception。发现执行的sql事务无法回滚。无奈只能在注解上加上rollbackFor = InvalidException.class。但是为了弄明白原因,断点调试到spring底层代码,发现这么一句代码
return (ex instanceof RuntimeException || ex instanceof Error);
就是说要想事务回滚你的异常要么派生自RuntimeException或者Error,于是把InvalidException改成集成RuntimeExcepiton,并且把注解中的rollbackFor去除,发现也是可以正常回滚。

 

使用@Transactional需要注意的问题:
1.只对 Error或者RuntimeException 异常生效,如果要其他事务要加上(rollbackFor = Exception.class)
2.注解只能应用到 public 可见度的方法上。 如果应用在protected、private或者 package可见度的方法上,也不会报错,不过事务设置不会起作用。
3.不能用try catch
4.数据库引擎要支持事务,如果是mysql,注意表要使用支持事务的引擎,比如innodb,如果是myisam,事务是不起作用的。

如果一定要用trycatch 可以手动在catch中加回滚  TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(
 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值