最近要去面试,有几个事务知识点需要复习下:
1:在同一个Service中。A方法存在事务,创建异常,事务回滚
事务A方法开启了事务,结果数据库中没有新增数据,因为异常而回滚了。
2:在同一个Service中,A没有事务,B有事务,A调用B方法。出现异常,但是事务不生效
如图所示,不看注释的代码。A不存在事务,B存在事务,B中存在错误,A去调用B的方法。
原始数据为:
结果是:A插入数据成功,B删除成功,虽然发生异常,但是不会回滚。
具体原因是:
调用delete的方法时,是采用了this来调用
当在一个类调用的时候,没有生成代理对象,是使用this来调用,结果就是不会去进行拦截来开启事务管理。
数据库最终效果:
55为新插入的数据,而50就被删除了数据。
2:在同一个Service中,A没有事务,B有事务,A调用B方法。出现异常,事务生效
在这里,调用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();
使用接口的方式,而不是使用实现类,否则会报错
结果: 新插入数据成功,但是异常导致删除数据出现回滚,没有删除