Spring 在事务边界中批处理整个作业

Spring batch entire Job in transaction boundary

我有一个可以使用 spring 批处理作业的用例,我可以按以下方式设计它。

1) 第一种方式:

Step1(Chunk oriented step):从文件中读取—>过滤,验证并将读取的行转换为DTO(数据传输对象),如果有错误,在 DTO 本身中存储错误 —> 检查是否有任何 DTO 有错误,如果没有则写入数据库。如果是,写入错误文件。

但是,这种方式的问题是——我需要事务边界中的整个 JOB。因此,如果任何块出现故障,那么我不想写入数据库,而是想回滚所有成功的写入,直到数据库中的那个点。如果任何块中出现故障,上述方式会强制我为所有成功的写入编写回滚逻辑。

2) 第二种方式

步骤 1(面向块的步骤):从文件中读取项目 —> 在 DTO(数据传输对象)中过滤、验证和转换读取的行。这确实将错误存储在 DTO 对象本身中。

步骤 2 (Tasklet):读取从步骤 1 创建的整个 DTO 列表(而不是块)—> 检查是否有任何 DTO 填充了错误。如果是,则中止写入数据库并使 JOB 失败。

在第二种方式中,我获得了块处理和缩放的所有好处。同时我为整个作业创建了事务边界。

PS: 两种方式在他们的第一步中不会有任何一步失败,如果有失败;错误存储在 DTO 对象本身中。因此,总是会创建 DTO 对象。

问题是 - 因为我是 Spring 批次的新手,所以采用第二种方式是否是一个很好的模式。有没有一种方法可以在步骤之间共享数据,以便整个 DTO 列表可供第二步使用(上面的第二种方式)?

在我看来,尝试在单个事务(即作业级别的事务)中处理整个文件不是可行的方法。我将分两步进行:

  • 第 1 步:处理输入并将错误写入文件
  • 第2步:这一步以step1为条件。如果在步骤 1 中没有检测到错误,则将数据保存到数据库中。

这种方法不需要将数据写入数据库并在出现错误时将其回滚(如您描述中的选项 1 所建议)。它只有在一切正常时才写入数据库。

此外,此方法不需要如选项 2 所建议的那样在内存中保存项目列表,这在内存使用方面可能效率低下,并且如果文件很大则性能不佳。