前言
==
- 在spring中为了保证数据的准确性。spring接入了数据库的事务。
- 事务的特性呢无非就是ACID 。 A=Atomicity(原子性); C=Consistency(一致性);I=isolation(隔离性); D=Durability(持久性)
- 而spring针对数据的四种隔离级别实现spring的事务传播属性。这里不做细化分讲
问题描述
====
- 在Spring中配置事务也很简单我们只要在启动类上添加相关注解并在AOP中配置切面拦截我们定义的方法或者直接通过
Transactional
来实现事务的配置。 - 但是在我的一个方法里居然发现事务失效了。
@Transactional
public ResultInfo getPayInfo(Long id) {
return this.getPaymentInfo(id);
}
- 我们在getPayInfo这个方法中调用了同级的另外一个方法getPaymentInfo。 两个方法我们都配置的事务切实两个不同的事务。
- 但是我在执行的时候发现最终效果并不是如此。在外部的方法getPayInfo事务是正常的。但是通过this.getPaymentInfo这个方法内部的事务根本没有生效。我在这个方法里特意写错进行异常报错。但是里面已经执行的数据并没有发生回滚。因为外部和内部是两个不同的事务所以外部本身就不收影响。
- 关于如何配置外部和内部事务不同这里也不赘述了。就是配置spring的传播属性。
问题分析
====
- 有问题是好事说明我们还有进步的空间。我们仔细想想事务是如何实现的。
- 其实spring是没有事务。spring的事务其实就是数据库的事务。spring只是负责转发
- 而spring实现事务就是保证使用的是同一个数据库connection 。 这个就是通过ThreadLocal实现的
- 而剩下connection的连接后就交由数据库管理了。事务的管理spring是基于aop进行拦截的。但是我们上述代码是通过this调用方法的。我们知道spring中的bean实际上不是真正的对象而是基于原生对象产生的代理对象。
- 只有代理对象才能通过spring的aop拦截。而this是直接通过内部进行调用的不会走aop的那么这里的事务就会失效。
总结
==
- 事务依赖于aop 。 this调用直接避开了aop 。所以没有了事务。
- 知其然不知其所以然。还是需要努力学习的。
我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!