首页 > 解决方案 > 事务边界中的Spring批处理整个作业

问题描述

我有一个用例,我可以使用弹簧批处理作业,我可以通过以下方式设计。

1)第一种方式:

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

但是,这种方式的问题是 - 我需要事务边界中的整个 JOB。因此,如果任何块中出现故障,那么我不想写入 DB 并且想要回滚所有成功的写入直到 DB 中的那个点。如果任何块出现故障,上述方式迫使我为所有成功的写入编写回滚逻辑。

2) 第二种方式

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

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

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

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

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

标签: spring-batchspring-batch-tasklet

解决方案


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

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

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

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


推荐阅读