Spring 事务白衣几个操作和回滚

Spring transaction whit several operations and rollback

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

  1. 将布尔 Updating 字段设置为 true 到数据库中。它用于避免访问与此值链接的文件系统和数据库信息(例如车队)
  2. 对数据库进行一些操作。例如更改日期、名称、值或其他字段。这些更改会影响更多数据库表。
  3. 更改文件系统和数据库
  4. 将布尔值 Updating 设置为 false

如您所想,我必须管理错误并启动回滚程序以恢复数据库和文件系统。 我对如何编写我的方法有一些疑问。我有:

从其他 classes 我调用服务方法来使用数据库但是如果我调用其中一些方法我将每个值写入数据库所以不可能抛出回滚,或者我错了? 第 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 完成时,该标志才会命中数据库。更改保留在休眠上下文中,直到 @Transactionl 方法结束。

因此,当您执行 changeDisplacement 时,其他人会来读取该标志 - 它会看到 false(因为您尚未将其写入数据库)。您可以通过 READ_UNCOMMITTED 获取它,但是否允许这样做取决于您的应用程序。

您可以使用 REQUIRES_NEW 的方法并将该标志设置为 true 并在恢复时更新该标志。

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

@Transactional 就可以了。唯一的事情是你需要将 applicationServices.setUpdating 的传播设置为 REQUIRES_NEW 以便它单独提交:

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

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