在方法上注释的 Spring @Transactional 是否确保在方法结束时准确地刷新数据?

Rah*_*nzo 7 java spring hibernate jpa transactions

我在 Spring 应用程序中使用 Java 和 Hibernate 作为持久性提供程序,有一个简化的场景:

@Transactional
void method1() { // some savings}

@Transactional
void method2() { // some savings}
Run Code Online (Sandbox Code Playgroud)

当我运行父方法时(未注释为事务)

void parentMethod() {
    method1();
    method2();
}
Run Code Online (Sandbox Code Playgroud)

我能否确保当该方法完成时,在调用该方法之前数据库中的更改会立即受到影响?或者更改可以稍后刷新到数据库,但会有一些延迟?

我对其他应用程序在 method1 完成时(以及在调用 method2 之前)立即看到数据库中所做的更改感兴趣

更新 我的父方法没有定义在同一个类中,并且我的父方法的类和事务所没有@Transactional注解

谢谢!

men*_*urg 7

对于你的问题...确保在方法结束时准确刷新数据?不,不是方法结束的确切时间,而是方法结束的最晚时间。

在事务中,您可以根据需要多次刷新当前状态。刷新意味着您将 JPA 会话与数据库同步。有关于此,请参阅Hibernate 文档。刷新并不意味着你的改变是持久的;如果事务稍后回滚,这些更改将自动恢复。提交操作执行不同的步骤,其中之一是确保JPA(例如Hibernate)会话与DB 同步,并且如果需要,调用flush 如果会话已经同步,则刷新将被跳过。

在您所写的注释中,类和方法parentMethod不是事务性的,并且method1()method2()在单独的类中定义的。在这种情况下,当method1()调用 时,将启动一个新事务。当该方法结束时,该事务将被提交。通过此方法对数据库所做的任何更改都将是持久的,即无论以后发生什么(例外,其他方法中的回滚),这些更改都将保留在数据库中。

可以在此处找到与您的案例相关的一些信息,因为以下信息很重要:

  1. 这些方法是否在同一个类中并且
  2. 如果使用Spring自带的AOP或者AspectJ。parentMethod此外,这取决于定义您的类。如果是事务性的,那么这两个调用将在现有事务中运行,并且在第一个调用提交后将不会再提交。

  • 1) 是的,将暂停外部交易。但是,当嵌套 is 方法完成时,其事务将在外部事务恢复之前提交(或在发生错误时回滚)。即,在调用“method2()”之前,将提交用于“method1()”的事务。2) 对于“提交”,我的意思是更改将“持久”。无论之后发生什么,持久的更改都不会被恢复。提交不等于刷新。即使不提交事务,您也可以触发刷新。但是执行commit的时候,如果需要的话也会触发flush。 (2认同)