transactional注解生效范围,transactional注解失效原因
场景1@Transactional注释标注方法如果修饰符是非公共方法,@transactional注释将不起作用。
例如,以下代码定义了一个错误的@Transactional注释实现,该注释限定默认访问器。
@ servicepublicclasstestserviceimpl { @ resourceprivatetestmappertestmapper; @ transactionalvoidinserttest ((intre=test mapper.insert ) newtest ) 10 ); if(re0 ) thrownewneedtointerceptexception (' need intercept ); }testmapper.insert(newtest(210 ); }测试用例:
@runwith(springrunner.class ) springboottestpublicclassdemotests { @ resourcetestserviceimpltestserviceimpl; @Testpublic void testInvoke () { testServiceImpl.insertTest ); }在测试用例中调用insertTest ) )不会打开事务,因此数据库将成功导入数据。
解决:
要解决此问题,请在insertTest ()方法中添加公共修饰符
场景2在同一类中使用this关键字调用自己类的方法,导致禁用@Transactional; 示例代码如下:
@ servicepublicclasstestserviceimpl { @ resourcetestmappertestmapper; @ transactionalpublicvoidinsert ((/常规公共修饰符的事务方法intre=testmapper.insert ) newtest ) 10 ); if(re0 ) thrownewneedtointerceptexception (' need intercept ); }testmapper.insert(newtest(210 ); }在}public void innerInvoke ()//类内部调用@Transactional标记的方法。 this.insert (; }测试用例
@runwith(springrunner.class ) springboottestpublicclassdemotests { @ resourcetestserviceimpltestserviceimpl; @Testpublic void testInvoke () { testServiceImpl.innerInvoke ); }运行测试用例并将数据成功插入数据库的异常导致事务没有回滚的原因与@Transactional的实现方式有关。
解决:
在类实例中引用自己的bean实例; 从bean实例中调用insert (方法
场景3在标记@Transactional的方法内部处理了所有异常; 方法内部不会向外部抛出任务异常,在这种情况下,事务不会回滚,示例代码如下:
@ servicepublicclasstestserviceimpl { @ resourcetestmappertestmapper; @ transactionalpublicvoidinserttestcatchexception () try(intre=testmapper.insert ) newtest () 10 ) ); if(re0 )//在运行期间抛出异常的thrownewneedtointerceptexception (' need intercept ); }testmapper.insert(newtest(210 ); } catch (可移植e )//捕获所有异常; 自己选择system.out.println (icatchexception ); }测试用例
@runwith(springrunner.class ) springboottestpublicclassdemotests { @ resourcetestserviceimpltestserviceimpl; @ testpublicvoidtestinvoke ((testserviceimpl.inserttestcatchexception ) ); }运行测试用例后,成功将数据插入数据库的事务成功启动,commit操作成功执行,没有回滚的原因是@Transactional实现没有捕获任何异常,代码正确
解决:
自己捕捉异常后,处理异常,再次抛出运行异常(RuntimeException ),让方法调用方最终决定异常处理。
@Transactional注释原理分析@Transactional是基于动态代理实现的; 也就是说,Spring中常说的AOP; 在源代码中,只有具有公共修饰符的方法才有效; 除非是公共方法,否则不进行代理。
提交和回退事务是通过确定事务方法是否发生异常来完成的;如果发生异常,则回退事务;否则,提交事务。
场景1和场景2可以成功插入数据的原因是事务没有正常打开。 也就是说没有事务。 场景三是事务成功,在方法内部有效处理异常后,没有重新抛出异常。 提交事务时,后续的第二次insert操作位于异常之后,不会执行。
用公众号读缙农寂寞的纸飞机