准备数据:
两条测试数据,{08feaf2e7e9b45a0a5f10c9b11feba32,测试1},{092703ac73d1442e881cf0ce9d352800,测试2}
两个测试方法,主方法testTransactional() ,子方法updateTest2
第一种情况,(两个方法在同一个类中)当主子方法都有事务的时候,抛出异常,事务回滚,数据不变。
当主子方法都有事务的时候,抛出异常,事务回滚,数据不变。(主有子有=有)
当主方法有事务,子方法没事务的时候,抛出异常,事务回滚,数据不变。(主有子无=有)
当主方法没有事务,子方法有事务的时候,抛出异常,事务回滚,数据不变。(主无子有=无)
当主子方法都没有事务的时候,抛出异常,事务回滚,数据不变。(主无子无=无)
上边几种情况说明了,同一个类中子方法上的@Transactional注解是不生效的,都是取决于主方法有没有事务
哪怕是加上了参数(propagation = Propagation.REQUIRES_NEW)也是没用的。
简单解释一下,@Transactional事务是Spring采用动态代理(AOP)来实现的,为我们的每个类生成一个代理对象。只有在代理对象之间进行调用时,可以触发AOP。
而在同一个类中,主方法调用子方法,调用的是原对象的方法,而不通过代理对象。所以Spring无法切到这次调用,也就无法通过注解保证事务性了。也就是说,在同一个类中的方法调用,则不会被方法拦截器拦截到,因此事务不会起作用。
看下面的第二种情况,我们通过走切面的逻辑测试一下。
第二种情况,(当两个方法不再同一个类中,把子方法注入(@Autowried)到主方法中)
当主子方法都有事务的时候,抛出异常,事务回滚,数据不变。(主有子有=有)
看一下日志,这时候子方法内的事务也是用的主方法事务。
修改一下,当我们把子方法的注解@Transactional加上参数(propagation = Propagation.REQUIRES_NEW)
这个时候会创建一个新的事务出来,子方法会有自己的事务
当主方法有事务,子方法没事务的时候,抛出异常,事务回滚,数据不变。(主有子无=有)
子方法是用的主方法的事务。
当主方法没有事务,子方法有事务的时候,抛出异常,事务回滚,数据改变。(主无子有=子有)
子方法是有事务的,主方法没事务,主方法的抛出异常不会影响子方法的数据
当子主方法都没有事务的时候,抛出异常,事务回滚,数据会改变,这个不用解释。(主无子无=无)