首页天道酬勤事务的注解@Transactional的属性,spring事务回滚注解

事务的注解@Transactional的属性,spring事务回滚注解

张世龙 05-06 01:10 118次浏览
前几天忙于工作的焦急,关于@Transactional的事务管理,经过仔细研究,取得了相当大的成果。 花了好几天测试整理,今天发表了。 我希望看到博客的老铁们能得到什么。 不说废话直接进入正题。 首先,我将简要介绍Spring事务的传播行为。 事务传播行为是指,如果在启动当前事务之前事务上下文已经存在,则有多个选项可以指定事务方法的执行行为。 TransactionDefinition定义包含几个表示传播行为的常量。 transaction definition.propagation _ required :参与事务(如果当前存在事务); 如果当前没有事务,请创建新事务。 这是默认值。 transaction definition.propagation _ requires _ new :创建新事务。 如果当前事务存在,则挂起当前事务。 transaction definition.propagation _ supports :加入事务(如果当前存在事务); 如果当前没有事务,请使用事务以外的其他方法继续执行。 transaction definition.propagation _ not _ supported :在非事务中执行,如果当前事务存在,则挂起当前事务。 transaction definition.propagation _ never :在非事务中执行,如果当前存在事务,则抛出异常。 transaction definition.propagation _ mandatory :加入事务(如果当前存在); 如果当前没有事务,则抛出异常。 transaction definition.propagation _ nested :创建要作为当前事务的嵌套事务运行的事务(如果当前事务存在)。 如果当前没有事务,则此值与transaction definition.propagation _ required相同。 接下来,我们将讨论Spring事务的回滚机制。 默认情况下,声明性事务管理(Spring的AOP )将回滚以进行未选中的执行。 Spring事务边界在调用业务方法之前启动,在业务方法执行完成后执行commitorrollback (spring的默认值取决于是否抛出runtimeException ) 如果方法具有try{}catch{}exceptione}{}处理,则try中的代码块将与事务管理分离,要启用事务,请在catch上执行throw new RuntimeExceptionxxxxx

x '; 这一点也是面试中被问到的事务失效的场面。

下面简单介绍一下@Transactional注释的基本实现方法。 当然,通过动态代理,动态代理分为JDK自身和CGLIB。 对此我也不多解释,今天的主题是如何将@Transactional对事物的控制应用于火的纯蓝。 哈哈~

最需要注意的是在@Transactional注解的方法中,再调用本类中的其他方法method2时,那么method2方法上的@Transactional注解是不!会!生!效!的!,但加上也没有错。 用图像简单地理解吧。这一点也是面试中会问到的事务失效的场景。

@Transactional注释AOP实现方式图解1代理对象在目标对象前后的方法扩展,即事务的提交和回滚。 那么,继续调用这个类的其他方法怎么样? 如下图所示

@Transactional注释AOP实现方式图解2可以看出,目标对象内部的自调用,即this .中指向的目标对象不执行方法的扩展。

先说第二个需要注意的地方,然后再说如何解决上面的第一个问题。 第二,@Transactional注释的方法必须是公共方法,也就是说必须是公共修饰符!

关于这个的理由,发表个人的理解吧。 因为JVM的动态代理是基于接口实现的,所以可以在代理类中增强目标方法,然后再考虑一下。 我没有访问权限,该怎么办,好吗,这也是我没有深入研究基础。 是个人的理解。

这里也输入问题吧。 我希望善良的河马能回复并告诉我。 既然JVM动态代理是基于接口实现的,那么当所有服务层都遵循接口和实现类的开发模式时是否会启用注释呢? 也就是说,如果controller层直接调用没有接口的服务层并对其进行注释,它也不会起作用。 这是因为懒惰,没有测试。 其中之一是因为没有人

要解决第一个问题,请考虑如何在方法中调用类中的其他方法。

在AopContext.currentProxy ()中检索并调用类的代理对象就可以了。 因为这是CGLIB实现,所以打开AOP当然也很简单。 在springboot启动类中添加注释@ enableaspectjautoproxy (expose proxy=true )就可以了,这样可以让大家自己进行搜索。 请注意,代理对象调用的方法也是公共修饰符。 否则,将无法获取方法中注入的bean,并报告空指针错误。

emmmm,我先呼叫

的方式和结果说下吧。自己简单写了代码,有点粗糙,就不要介意啦,嘿嘿。。。

Controller中调用Service

@RestControllerpublic class TransactionalController { @Autowired private TransactionalService transactionalService; @PostMapping("transactionalTest") public void transacionalTest(){ transactionalService.transactionalMethod(); }}

Service中实现对事务的控制:接口

public interface TransactionalService { void transactionalMethod();}

Service中实现对事务的控制:实现类        (各种情况的说明都写在图片里了,这样方便阅读,有助于快速理解吧)

上面两种情况不管使不使用代理调用方法1和方法2,方法transactionalMethod都处在一个事务中,四条更新操作全部失败。

那么有人可能会有疑问了,在方法1和方法2上都加@Transactional注解呢?答案是结果和上面是一致的。

小结只要方法transactionalMethod上有注解,并且方法1和方法2都处于当前事务中(不使用代理调用,方法1和方法2上的@Transactional注解是不生效的;使用代理,需要方法1和方法2都处在transactionalMethod方法的事务中,默认或者嵌套事务均可,当然也可以不加@Transactional注解),那么整体保持事务一致性。

如果想要方法1和方法2均单独保持事务一致性怎么办呢,刚说过了,如果不是用代理调用@Transactional注解是不生效的,所以一定要使用代理调用实现,然后让方法1和方法2分别单独开启新的事务,便OK啦。下面摆上图片。

这两种情况都是方法1和方法2均处在单独的事务中,各自保持事务的一致性。

接下来进行进一步的优化,可以在transactionalMethod方法中分别对方法1和方法2进行控制。要将代码的艺术发挥到极致嘛,下面装逼开始。

代码太长了,超过屏幕了,粘贴出来截的图,红框注释需要仔细看,希望不要影响你的阅读体验,至此,本篇关于@Transactioinal注解的使用就到此为止啦,

简单总结一下吧:

1、就是@Transactional注解保证的是每个方法处在一个事务,如果有try一定在catch中抛出运行时异常。

2、方法必须是public修饰符。否则注解不会生效,但是加了注解也没啥毛病,不会报错,只是没卵用而已。

3、this.本方法的调用,被调用方法上注解是不生效的,因为无法再次进行切面增强。

如果有更细致的讨论欢迎评论,感谢阅读。

 

win7提高开机速度,win7旗舰版开机超级慢