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

问题描述

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

1) 第一种方式:

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

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

2) 第二种方式

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

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

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

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

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

解决方法

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

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

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

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

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...