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

时间:2017-09-14 06:16:48

标签: java spring spring-boot transactions

当我从另一个事务方法调用一个事务方法时会发生什么,现在我的第二个事务方法已经完成,并且它在第一个事务方法中返回,并且不幸的是它失败了,所以它将回滚所有内容,意味着它将回滚第二个事务方法改变.. ??注意:两种方法都属于同一类

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

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

所以在上面的例子中它会回滚我在第二个事务方法中保存的内容吗?

6 个答案:

答案 0 :(得分:5)

这取决于txType。默认情况下,它是必需的。因此第一种方法启动事务,同一事务用于调用method2。

另外请注意,同一对象内的方法调用不会触发事务处理。通常,事务处理作为代理处理,仅在调用注入的其他bean时才起作用。在你的例子中,你不会注意到差异。

这种情况很重要,如果method1不是@Transactional而method2是。在这种情况下,根本就没有交易。

答案 1 :(得分:2)

如果两个方法都在同一个类中,calling from another method of the same class时甚至不会考虑@Transactional注释。你把它放在那里,或者即使你把它放在一边并不重要。仍然会有一个由method1()启动的交易,但之后你就陷入了这个交易。

如果第二个方法在一个单独的类中,您可以使用Propagation.REQUIRES_NEW让它在自己的事务中运行,这意味着即使method1()稍后失败,method2()中的任何更改仍然会做。

REQUIRED的默认事务传播如果不存在则启动新事务,或者加入现有事务。同样,在单独的类情况下,当method2()失败时,它会导致回滚method1()中所做的任何更改。

答案 2 :(得分:1)

Spring boot提供了 @Transactions 的传播概念。传播级别决定内部事务应该是同一个外部事务的一部分,或者应该是不同的事务。默认情况下,传播级别为 REQUIRED ,这意味着内部事务将成为同一外部事务的一部分,因此如果内部事务失败,则整个事务将进行回滚。

现在知道Rollback默认只运行Runtime异常非常重要。对于已检查的异常,您必须明确指定 @Transcations(rollbackFor = Exception.class)

所以回答你的问题是肯定的!它执行内部事务所做的回滚更改。

答案 3 :(得分:0)

发生的情况取决于所选的交易传播。默认值为:“REQUIRED”表示如果不存在任何交易,则会启动。

因此,在您的代码中,method2将加入为method1创建的现有事务。

对于同一类中两种方法的情况,请注意,因为Spring代理对象的工作方式不会如预期的那样。

答案 4 :(得分:0)

这取决于您的transaction propagation配置。

相关官方文档在这里

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

只需注意图表,传播定义了一个事务"事务上下文"。

答案 5 :(得分:0)

这是一个典型的问题:

  1. 您应该通过自注入对象调用method2()或使用this表示法,因为另一种方法将调用method2并避免调用代理对象方法,它包含所有事务逻辑。
      

    在代理模式(默认设置)下,只拦截通过代理进入的外部方法调用。这意味着实际上,自调用目标对象中的一个方法调用目标对象的另一个方法,即使被调用的方法用@Transactional标记,也不会在运行时导致实际的事务。此外,代理必须完全初始化以提供预期的行为,因此您不应该在初始化代码中依赖此功能,即@PostConstruct

  2. 嵌套事务行为取决于@Transactional参数。例如 - 使用PROPAGATION_REQUIRES_NEW@Transactional的嵌套方法创建新事务。查看official doc
  3. 中的更多信息