Java 包含多个操作和回滚的Spring事务

Java 包含多个操作和回滚的Spring事务,java,mysql,spring,transactions,rollback,Java,Mysql,Spring,Transactions,Rollback,我必须编写一些方法将值更改为数据库,并在文件系统上进行一些操作。 因此,我必须进行以下步骤: 将布尔值更新字段设置为真到数据库中。它用于避免访问与此值链接的文件系统和数据库信息(例如车队) 对数据库进行一些操作。例如,更改日期、名称、值或其他字段。这些更改会影响更多的数据库表 对文件系统和数据库进行更改 将布尔值更新设置为false 可以想象,我必须管理错误并启动回滚过程来恢复数据库和文件系统。 我对如何编写我的方法有些怀疑。我有: 实体 扩展了JpaRepository的存储库接口,并具有从

我必须编写一些方法将值更改为数据库,并在文件系统上进行一些操作。 因此,我必须进行以下步骤:

  • 将布尔值
    更新
    字段设置为
    到数据库中。它用于避免访问与此值链接的文件系统和数据库信息(例如车队)
  • 对数据库进行一些操作。例如,更改日期、名称、值或其他字段。这些更改会影响更多的数据库表
  • 对文件系统和数据库进行更改
  • 将布尔值
    更新
    设置为false
  • 可以想象,我必须管理错误并启动回滚过程来恢复数据库和文件系统。 我对如何编写我的方法有些怀疑。我有:

    • 实体
    • 扩展了
      JpaRepository
      的存储库接口,并具有从方法名称创建的查询和
      @Query
      注释的
      @Transactional
      (否则我收到错误)
    • 服务接口
    • 包含对数据库进行简单更改的所有方法的服务实现。此类用
      @Transactional
    从其他类中,我调用服务方法来使用数据库,但如果调用其中的一些方法,我会将每个值写入数据库,这样就不可能抛出回滚,或者我错了? 步骤1必须立即写入数据库,而其他更改应该是使用@Transactional属性,但只需将@Transactional添加到我的方法中就足够了?对于文件系统回滚,我创建所有子文件夹的备份,并在出现错误时恢复它们。 例如:

    @Transactional(rollbackFor=FileSystemException.class)
    private void changeDisplacement(int idApplication, int idDisplacement){
        applicationServices.setUpdating(true); //this has be to write immediatly into database so that the other methods can stop using this application
        Application application = applicationServices.getId(idApplication);
        application.setDisplacement(displacementServices.getId(idDisplacement));
    
        //OTHER OPERATIONS ON DIFFERENT TABLES
    
        //OPERATIONS ON FILE SYSTEM CATCHING ALL EXCEPTION WITH TRY-CATCH AND IN THE CATCH RESTORE FILESYSTEM AND THROW FileSystemException to start database rollback
        //In the finally clause use applicationServices.setUpdating(false)  
    }
    
    它是否可以使用此逻辑,或者此处的
    @Transactional
    字段错误?
    谢谢

    这里有多个问题,有些问题很难理解,这里有一些输入。当你有这个:

    @Transactional(rollbackFor=FileSystemException.class)
    private void changeDisplacement(int idApplication, int idDisplacement){
        applicationServices.setUpdating(true);
    
    只有当
    @Transactional
    完成时,该标志才会命中数据库。更改将保留在hibernate上下文中,直到
    @Transactionl
    方法结束

    因此,当您执行
    changeplacement
    而其他人来读取该标志时,它将看到false(因为您还没有将其写入数据库)。您可以通过
    READ_UNCOMMITTED
    获得它,但如果您允许,则由您的应用程序决定

    您可以使用
    REQUIRES_NEW
    的方法,并在那里将该标志设置为true,如果要恢复,请将该标志重新更新


    通常,更新数据库和文件系统并不容易(保持同步)。我以前做过的方法(可能是更好的选择)是注册事件(一旦创建了正确的数据库),然后写入文件系统

    这里有多个问题,有些问题很难理解,这里有一些输入。当你有这个:

    @Transactional(rollbackFor=FileSystemException.class)
    private void changeDisplacement(int idApplication, int idDisplacement){
        applicationServices.setUpdating(true);
    
    只有当
    @Transactional
    完成时,该标志才会命中数据库。更改将保留在hibernate上下文中,直到
    @Transactionl
    方法结束

    因此,当您执行
    changeplacement
    而其他人来读取该标志时,它将看到false(因为您还没有将其写入数据库)。您可以通过
    READ_UNCOMMITTED
    获得它,但如果您允许,则由您的应用程序决定

    您可以使用
    REQUIRES_NEW
    的方法,并在那里将该标志设置为true,如果要恢复,请将该标志重新更新


    通常,更新数据库和文件系统并不容易(保持同步)。我以前做过的方法(可能是更好的选择)是注册事件(一旦创建了正确的数据库),然后写入文件系统

    @Transactional
    在这里可以。唯一的问题是您需要设置
    应用程序服务的传播。setUpdating
    需要\u NEW
    以便单独提交:

    public class ApplicationServices {
        @Transactional(propagation=Propagation.REQUIRES_NEW)
        public void setUpdating(boolean b) {
            // update DB here
        }
    }
    

    在异常情况下,只要您在finally块中调用了
    setUpdating
    ,它仍然会更新数据库。

    @Transactional
    在这里是可以的。唯一的问题是您需要设置
    应用程序服务的传播。setUpdating
    需要\u NEW
    以便单独提交:

    public class ApplicationServices {
        @Transactional(propagation=Propagation.REQUIRES_NEW)
        public void setUpdating(boolean b) {
            // update DB here
        }
    }
    

    在异常的情况下,只要您在finally块中调用
    setUpdating
    ,它仍然会更新数据库。

    我认为您无法保证文件还原阶段,如果在写入文件时抛出异常,则很可能再次写入,以还原其状态,也会失败。当然,我将尝试只更新一次,如果还原失败,我会发送电子邮件并保持文件系统锁定,直到手动操作解决问题。我认为您无法保证文件还原阶段,如果在写入文件时引发异常,则很可能再次写入,以恢复其状态,也会失败。确定,我将尝试只更新一次,如果还原失败,我将发送电子邮件并保持文件系统锁定,直到手动操作解决问题。谢谢,此批注创建了一个新事务,暂时停止主事务,对吗?因此,如果使用
    @Transactional
    注释的方法调用具有相同注释的其他方法,则只在主注释的和处写入数据库中的值?
    setUpdating
    方法使用新的TX,而不依赖调用方方法的事务。如果操作成功,它将提交,其他TX将看到data.perfect,问题的第二部分是我是怎么想的?如果第二部分是指回滚文件系统,那么您必须自己做。Spring事务对您执行的文件系统操作没有任何线索。OIC,是的,如果您不指定传播,它们都共享相同的TX,并且在最外层的方法完成后TX被提交。谢谢,