Spring 事务内部机制

6
以下是翻译的结果:

情况如下:

  1. Method1 中包含四个数据库更新方法。Method1 使用 Spring 事务管理语义进行注释。

  2. Method2 中包含一个数据库读取方法,并且在 Method1 执行完所有数据库更新后被调用。Method2 同样使用 Spring 事务语义进行注释。

  3. 有一个 web 请求,控制器拦截请求并调用 method1,然后调用 method2。

  4. 一个事务也包装在 web 请求周围。

我感兴趣的是:

1.Spring 如何知道在事务成功时提交数据库更新?是否有一些参考 Spring 实现事务管理的内容?

2.由于我们有事务层次结构:环绕 web 请求的事务 -> 对于 Method1 的传播方式为 RequestNew 的事务 -> 对于 Method2 的传播方式为 Required 的事务,Spring 如何进行事务管理以确保事务在正确上下文中以正确顺序执行?

简而言之,了解 Spring 在所有细节上如何执行事务管理或者提供不仅仅手摇JTA或其他首字母缩写的解释说明的文档将是很棒的。

谢谢

3个回答

11
让我们做一些基本陈述。
  1. 事务上下文是一个环境,其中某些特殊属性(数据库会话)可用于应用程序运行时,否则不可用。事务上下文通常用于范围事务。
  2. Spring使用AOP代理和XML元数据实现声明式事务管理。
  3. 注释用于标记特定方法的事务传播行为。
  4. Spring使用拦截器机制在方法上应用事务。
这里我正在重复@stacker上方给出的示例。
MyClass{

    @Transactional
    public void sequence() {
      method1();
      method2();
    }

    @Transactional
    void method1() {
    }

    @Transactional(propagation=Propagation.REQUIRES_NEW)
    void method2() {
    }

}

你也可以使用XML配置来实现相同的功能。让我们以此为例,因为它很受欢迎并被广泛使用。
在部署时。
  • Spring framework checks the xml configuration files (famed applicationContext.xml) and depending on the configuration, scans the code for @Transactional annotation (assuming that the configuration is mentioned as annotation based).
  • After this, it generates AOP proxies for methods marked for transaction. In simple terms, these proxies are nothing but wrapper around the concerned methods.
  • Within these wrapper methods, before and after a Transaction Advisor code is also generated depending on the configuration (namely the transaction propagation).
  • Now when these wrapper methods are invoked Transaction Advisor comes into picture before and after the actual method call. .
  • Representing the same in pseudo code for the example above

      ProxyMyClass{   
        MyClass myclass;
        .
        .
        .
        sequence(){
         //Transaction Advisor code (Typically begin/check for transaction)
         myclass.sequence();
         //Transaction Advisor code(Typically rollback/commit)
        }
        .
        .
        .
        }
    
这是Spring如何管理事务的方式。尽管有些过于简化。
现在回答你的问题,
1. Spring如何知道在成功事务之后提交数据库更新?是否有对Spring实现进行事务管理的参考?
每当您调用一个事务方法时,实际上调用的是代理。该代理首先执行事务顾问(将开始事务),然后调用实际的业务方法,一旦完成,另一个事务顾问执行(根据方法返回的方式,将提交或回滚事务)。
2. 由于我们有一个事务层次结构:围绕Web请求的事务->传播= RequestNew的Method1的事务->传播= Required的Method2的事务,Spring如何进行事务管理以确保事务在适当的上下文中以正确的顺序执行?
在事务层次结构的情况下,Spring框架会相应地生成事务顾问检查。针对您提到的示例:
- 对于Method1(RequestNew),Transaction Advisor代码(或事务建议)将始终创建新事务。 - 对于Method2(Required),Transaction Advisor代码(或事务建议)将检查现有的事务并在存在的情况下使用它,否则将创建新事务。
在Spring文档页面上有一张image非常好地总结了这些方面。

Typical Spring Transaction Management

希望这有所帮助。

这是一次非常出色的解释。谢谢。 - sc_ray
请问在上面的图表中,呼叫者是控制器还是Web请求? - tintin
@tintin,调用者是控制器还是其他什么并不重要。最终它将是从某个类到代理的方法调用。 - Santosh

4
Controller
@Transactional
public void sequence() {
  method1();
  method2();
}

@Transactional
void method1() {
}

@Transactional(propagation=Propagation.REQUIRES_NEW)
void method2() {
}

默认传播行为是REQUIRED(支持当前事务,如果不存在则创建一个新的)。因此,m1将使用在Controller中启动的事务。m2被注释为REQUIRES_NEW(创建一个新的事务,如果存在则挂起当前事务)。事务的顺序是调用事务方法的顺序。

Controller
begin tx1
   |--------------------> m1 (uses tx1)
   |
   | begin tx2
   |--------------------> m2 (uses tx2)
   | commit tx2
commit tx1

在典型的MVC环境中,事务是从控制器级别开始的吗?还是从带有@Transactional注释的服务层开始,由控制器调用? - tintin
@tintin 如果您有“低级别”的服务,您可能希望将它们合并到不同的事务中(针对不同的操作),因此您应该在控制器中启动事务。使用@Transactional注释的方法会加入现有的事务(例如在控制器中启动的事务)。 - stacker

0

你有没有阅读过Spring文档?基本上AOP用于管理事务。你还应该阅读AOP文档。如果AOP文档不够,我建议你浏览代码。在断点调试模式下逐步执行代码会很有帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接