日常开发踩坑:你的"事务"真的见效了吗?
对于“事务”,很多读者尤其是业务研发通常采用“一笔带过”的解决方式:方法上用注解公告,而后就“安心”的写代码去了。
但事务真的见效了吗?复杂的嵌套事务应该如何解决?正确回滚了吗?本篇就针对这些坑点为读者做科普和预警。
同名公众号:浩说编程 [ 大厂技术资源 | Java经典电子书 | 研发必备安装包 | 限时免费获取 ]
一、公告问题导致的事务失效
先用例子测试一下,定义客户Controller,并注入Service来调用创立客户方法:
构建Service服务,向controller暴露公有方法createUser,方法内部经过校验逻辑后,调用公告事务的私有方法doCreateUser实现入库逻辑以及后续关联业务解决逻辑:
期望结果:当第18行的逻辑发生异常之后,16行的入库操作进行回滚。
实际结果:经过测试,发生异常的情况下,数据库中的数据并未回滚,事务并未见效!
坑点:事务公告注解@Transactional只有定义在Public修饰的方法上才会见效
于是尝试修改一下Service层代码第14行:
再次测试:发生异常的情况下,数据仍然没有回滚!这又是为什么呢?
起因在于:注解方式的事务公告@Transactinal是基于AOP的,而AOP的底层是通过动态代理商模式来实现,也就是说事务的回滚逻辑其实是存在于代理商类的方法加强逻辑中。
补课通道
设计模式的浅显了解–代理商模式
坑点:想要事务生效必需通过代理商类来调用事物方法doCreateUser(),而this并不是指代理商类。
再次修改代码:先创立UserService的代理商(注入UserService),通过通过代理商调用事务方法doCreateUser()
测试结果:当第24行的逻辑发生异常之后,22行的入库操作正常回滚,与期望结果一致!
不过我们在UserService里又注入了UserService自己,这很鸡肋,所以再修改一下UserService:
二、异常解决导致的事务失效
在实际开发中我们可能需要对代码中可能的异常做catch操作:
测试结果:当代码第14行发生异常后,进入catch,但12行的数据并未回滚。
坑点:公告事务的方法中假如自己设置了异常捕获catch逻辑,事务将无法回滚。
处理方案:手动设置事务回滚,修改catch中的代码
异常解决的另一种情况是直接抛出:
测试结果:当第13行发生空指针异常NullPointerException时,异常被抛出,事务也无法回滚。
坑点:公告事务的方法在发生指定抛出的异常类型时,事务无法回滚。
处理方案:在@Transactional注解中公告事务回滚支持的异常类型
三、嵌套事务的回滚逻辑错误
事务解决还有一个经常遇到的情况是:在方法中需要对多个表进行升级操作,这就涉及到多事务同时操作。
还是用开始的例子,我们在创立客户之后添加日志记录操作,将日志入库:
构建LogService类,日志入库方法insertLog()公告事务:
通过代码可以看到,我在主事务方法中包含了日志入库的子事务方法,那么当子事务回滚,按照之前讲的:主事务做了catch,所以理论上主事务应该不会回滚了。而实际的测试情况是:主事务仍然发生了回滚,这就是嵌套事务的特别之处。
日志解决并非主业务,我们更希望即使日志解决回滚了也不应该影响创立客户操作的正常提交。
坑点:假如我们希望子事务的回滚不影响上级事务的提交,需要在子事务的@Transactional注解中公告事务传播策略
修改之后日志解决回滚的情况下,创立客户操作仍然正常提交,满足业务需要。
以上就是“事务”解决的少量坑点,希望读者看过本篇之后对这一部分重视起来,我们下期继续踩坑。
同名公众号:浩说编程 [ 大厂技术资源 | Java经典电子书 | 研发必备安装包 | 限时免费获取 ]
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 日常开发踩坑:你的"事务"真的见效了吗?