简体   繁体   English

从另一个@Transactional注释方法调用@Transactional注释方法

[英]Call @Transactional annotated method from another @Transactional annotated method

What happens when I call one transactional method from another transactional method, now my second transactional method completed, and it came back in 1st transactional method, and unfortunately it fail, so will it roll back everything, means will it roll back 2nd transactional method changes..?? 当我从另一个事务方法调用一个事务方法时,会发生什么,现在我的第二个事务方法已经完成,并且它在第一个事务方法中返回,并且不幸的是它失败了,所以它将回滚所有内容,意味着它将回滚第二个事务方法更改?? Note: both method are in same class 注意:两种方法都属于同一类

@Transactional 
public void method1(){
   //do something
   call method2();
  //do something
  ...
  ...
  failed here
}

@Transactional
public void method2(){
  //do something
  save()
}

So in above example will it rollback whatever I saved in 2nd transactional method? 那么在上面的例子中它会回滚我在第二个事务方法中保存的内容吗?

It depends on the txType. 这取决于txType。 By default it is REQUIRED. 默认情况下,它是必需的。 So the first method starts the transaction and the same transaction is used for the call to method2. 因此第一种方法启动事务,同一事务用于调用method2。

Also be careful that a method call inside the same object does not trigger the transaction processing. 还要注意,同一对象内的方法调用不会触发事务处理。 As typically the transaction handling is handled as proxy that only works when calling an injected other bean. 通常,事务处理作为代理处理,仅在调用注入的其他bean时才起作用。 In your example you would not notice a difference though. 在你的例子中,你不会注意到差异。

A case where this would matter is if method1 is not @Transactional and method2 is. 这很重要的情况是,如果method1不是@Transactional而method2是。 In this case there would be no transaction at all. 在这种情况下,根本就没有交易。

If both methods are in the same class, the @Transactional annotation won't even be considered when calling from another method of the same class . 如果两个方法都在同一个类中, 则从同一个类的另一个方法调用时甚至不会考虑@Transactional注释。 It doesn't matter what you put there, or even if you leave it out. 你把它放在那里,或者即使你把它放在一边并不重要。 There still will be a transaction started by method1() , but then you're stuck in that transaction. 仍然会有一个由method1()启动的事务,但是你会陷入该事务中。

If the second method were in a separate class, you could use Propagation.REQUIRES_NEW to have it run in its own transaction, meaning that even if method1() later on failed, any changes in method2() would still have made. 如果第二个方法在一个单独的类中,你可以使用Propagation.REQUIRES_NEW让它在自己的事务中运行,这意味着即使稍后的method1()失败, method2()任何更改仍然会发生。

The default transaction propagation of REQUIRED starts a new transaction if none exist, or joins an existing transaction. 如果不存在,则REQUIRED的默认事务传播将启动新事务,或者加入现有事务。 Again, in the separate class situation it results in the rollback of any changes made in method2() when method1() fails. 同样,在单独的类情况下,当method1()失败时,它会导致回滚method2()所做的任何更改。

Spring boot provides concept of propagation with @Transactions . Spring引导提供了使用@Transactions进行传播的概念。 Propagation level decides that inner transaction should be part of same outer transaction or it should be different isolated one. 传播级别决定内部事务应该是同一个外部事务的一部分,或者应该是不同的事务。 By default propagation level is REQUIRED which means inner transaction will be part of same outer transaction, so if inner transaction fails whole transaction will get rollback. 默认情况下,传播级别为REQUIRED ,这意味着内部事务将是同一外部事务的一部分,因此如果内部事务失败,则整个事务将获得回滚。

Now its important to know that Rollback works for only Runtime exceptions by default. 现在重要的是要知道Rollback默认只适用于运行时异常。 For checked Exceptions you have to specify that explicitly @Transcations(rollbackFor = Exception.class) 对于已检查的异常,您必须明确指定@Transcations(rollbackFor = Exception.class)

So to answer for your question is YES! 所以回答你的问题是肯定的! It does rollback changes made by inner transaction. 它执行内部事务所做的回滚更改。

What happens depends on the chosen transaction propagation. 发生的情况取决于所选的事务传播。 Default is: "REQUIRED" which means that if no transaction exists it will be started. 默认值为:“REQUIRED”表示如果不存在任何事务,则将启动它。

So in your code method2 will join existing transaction created for method1. 因此,在您的代码中,method2将加入为method1创建的现有事务。

As for your case with both methods in the same class, be careful as this will not work as you expect because of the way Spring proxy objects work. 至于你在同一个类中使用这两个方法的情况,要小心,因为Spring代理对象的工作方式不会像你期望的那样工作。

It depends on your transaction propagation config. 这取决于您的transaction propagation配置。

Related official doc is here 相关官方文档在这里

https://docs.spring.io/spring/docs/current/spring-framework-reference/html/transaction.html#tx-propagation https://docs.spring.io/spring/docs/current/spring-framework-reference/html/transaction.html#tx-propagation

Just note the graph, propagation define a transaction's "transaction context". 只需注意图表,传播定义了一个事务的“事务上下文”。

this is a typical question: 这是一个典型的问题:

  1. You should call method2() by self injected object or use this notation, because another ways will call method2 and avoid call proxy object method, which contain all transactional logic. 您应该通过自注入对象调用method2()或使用this表示法,因为另一种方法将调用method2并避免调用代理对象方法,它包含所有事务逻辑。

    In proxy mode (which is the default), only external method calls coming in through the proxy are intercepted. 在代理模式(默认设置)下,只拦截通过代理进入的外部方法调用。 This means that self-invocation, in effect, a method within the target object calling another method of the target object, will not lead to an actual transaction at runtime even if the invoked method is marked with @Transactional. 这意味着实际上,自调用目标对象中的一个方法调用目标对象的另一个方法,即使被调用的方法用@Transactional标记,也不会在运行时导致实际的事务。 Also, the proxy must be fully initialized to provide the expected behaviour so you should not rely on this feature in your initialization code, ie @PostConstruct 此外,必须完全初始化代理以提供预期的行为,因此您不应该在初始化代码中依赖此功能,即@PostConstruct

  2. Nested Transaction behaviour depends on @Transactional parameters. 嵌套事务行为取决于@Transactional参数。 For example - Use PROPAGATION_REQUIRES_NEW for create new transaction for nested methods with @Transactional . 例如 - 使用PROPAGATION_REQUIRES_NEW@Transactional嵌套方法创建新事务。 See more info in official doc 官方文档中查看更多信息

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 回滚 @Transactional 注释的方法 - Rollback a @Transactional annotated method 与方法注解者@Transactional的通信 - Communication to caller of method annotated @Transactional 在实体上没有合并调用的Spring事务注释方法 - spring transactional annotated method without merge call on entities Spring AOP:具有@Transactional注释方法的方法的注释切入点? - Spring AOP : Annotated pointcuts for a method with @Transactional annotated method? 从Spring Boot测试调用的@Caching方法[注有@Transactional]无法正常工作 - @Caching method called from spring boot test [annotated with @Transactional] not working 如何在@Transactional带注释的方法中将状态提交给DB? - How to commit status to DB within @Transactional annotated method? 当@Transactional注释方法被多个实例并行命中时会发生什么? - What happens when a @Transactional annotated method is hit in parallel by multiple instances? 如果在内部@Spring注释了方法,则Spring @Transactional注释方法是否会覆盖@Transactional(readOnly = true)方法? - Does a Spring @Transactional annotated method overwrite an @Transactional(readOnly=true) method if called within it? 从服务类中调用时,Spring @Transactional不适用于带注释的方法 - Spring @Transactional doesn't work for an annotated method when called from within service class Spring 没有为 @service 注释的 class 创建 bean,当它的方法之一用 @transactional 注释时 - Spring is not creating the bean for @service annotated class when one of its method is annotated with @transactional
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM