@Transactional注释方法是否等待Spring中的成功提交?

时间:2016-06-08 20:37:54

标签: java spring spring-transactions

在Spring中使用@Transactional带注释的方法时,带注释的方法的返回是否与底层数据库事务的成功提交同步?

(这假设事务在返回后实际上会提交,根据所选的传播方法可能不是这种情况。)

如果等待提交不是默认行为,是否可以通过配置或其他方式启用它?

我的问题的动机是我希望实现一个可靠的“存储转发”类型端点,该端点仅在调用的效果已经提交后才返回客户端的响应稳定的存储。这可能与@Transactional完全相同吗?

4 个答案:

答案 0 :(得分:2)

简短回答是否定的:该方法不等待提交。

实际发生的事情取决于两个因素:

  • 在调用方法之前是否存在事务?
  • 使用的交易传播是什么?

如果没有预先存在的事务,则在调用该方法之前会创建一个新事务,如果它还没有被标记为仅回滚,则Spring会在该方法返回后立即尝试提交它 - 在这种情况下,即使该方法不等待提交,提交立即执行。

由于嵌套调用,当物理事务已经存在时调用事务性注释方法,事情变得更加困难

摘自Spring参考手册:

  

当传播设置为PROPAGATION_REQUIRED时,将为应用该设置的每个方法创建逻辑事务范围。每个这样的逻辑事务范围可以单独确定仅回滚状态,外部事务范围在逻辑上独立于内部事务范围。当然,在标准PROPAGATION_REQUIRED行为的情况下,所有这些范围将映射到同一物理事务。因此,内部事务范围中的仅回滚标记集确实会影响外部事务实际提交的机会

     与PROPAGATION_REQUIRED相比,PROPAGATION_REQUIRES_NEW对每个受影响的事务范围使用完全独立的事务。在这种情况下,底层物理事务是不同的,因此可以独立提交或回滚,外部事务不受内部事务的回滚状态的影响。

     

PROPAGATION_NESTED使用可以回滚到的多个保存点的单个物理事务。这种部分回滚允许内部事务作用域触发其作用域的回滚,外部事务能够继续物理事务,尽管已经回滚了一些操作。

这意味着除了PROPAGATION_REQUIRES_NEW之外,在包含事务结束之前不会尝试提交。

换句话说,如果您希望在事务注释方法结束后立即进行提交,则必须将传播设置为PROPAGATION_REQUIRES_NEW:@Transactional(propagation=Propagation.REQUIRES_NEW)

答案 1 :(得分:0)

如果您没有使用@Transactional,那么您将如何处理它?它将类似于以下代码块

UserTransaction utx = entityManager.getTransaction(); 

try { 
    utx.begin(); 

    businessLogic();

    utx.commit(); 
} catch(Exception ex) { 
    utx.rollback(); 
    throw ex; 
}

@Transactional实际上对你做同样的事情。所以你可以看到它是在业务逻辑之后处理的。

我从这个精彩的blog复制了代码。您可以查看此信息以了解更多详细信息。

答案 2 :(得分:0)

我在保存交易中尝试了PROPAGATION_REQUIRES_NEW,这对我有效。

答案 3 :(得分:-1)

我使用了参数isolation = Isolation.SERIALIZABLE,因此在事务实际提交之后,将完成一种方法。 (顺便说一下,我将@Transactional放在Spring引导项目中的控制器方法之上。)