Spring事务学习

最近要去面试,有几个事务知识点需要复习下:

1:在同一个Service中。A方法存在事务,创建异常,事务回滚

事务1.jpg

事务A方法开启了事务,结果数据库中没有新增数据,因为异常而回滚了。

2:在同一个Service中,A没有事务,B有事务,A调用B方法。出现异常,但是事务不生效

事务 2.jpg

如图所示,不看注释的代码。A不存在事务,B存在事务,B中存在错误,A去调用B的方法。

原始数据为:


数据 4.jpg

结果是:A插入数据成功,B删除成功,虽然发生异常,但是不会回滚。

具体原因是:


原始调用链路 9.jpg

调用delete的方法时,是采用了this来调用
当在一个类调用的时候,没有生成代理对象,是使用this来调用,结果就是不会去进行拦截来开启事务管理。
数据库最终效果:


数据6.jpg

55为新插入的数据,而50就被删除了数据。

2:在同一个Service中,A没有事务,B有事务,A调用B方法。出现异常,事务生效

调用链路 8.jpg

在这里,调用delete的方法是代理类来调用了。
下面是解决方案:

  • 1.把方法B抽离到另外一个XXService中去,并且在这个Service中注入XXService,使用XXService调用方法B;
    显然,这种方式一点也不优雅,且要产生很多冗余文件,看起来很烦,实际开发中也几乎没人这么做吧?.反正我不建议
    采用此方案;

  • 2.通过在方法内部获得当前类代理对象的方式,通过代理对象调用方法B

    上面说了:动态代理最终都是要调用原始对象的,而原始对象在去调用方法时,是不会再触发代理了!

    所以我们就使用代理对象来调用,就会触发事务;

获取代理对象的方法:

1.使用 ApplicationContext 上下文对象获取该对象;
2.使用 AopContext.currentProxy() 获取代理对象,但是需要配置exposeProxy=true

启动类加上注解: @EnableAspectJAutoProxy(exposeProxy = true)
PlusService plusService = (PlusService) AopContext.currentProxy();
使用接口的方式,而不是使用实现类,否则会报错

结果: 新插入数据成功,但是异常导致删除数据出现回滚,没有删除


数据 7.jpg
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容