我正在尝试了解Spring Batch如何进行事务管理。这不是一个技术问题,而是概念问题:Spring Batch使用什么方法以及该方法的后果是什么?
让我试着澄清一下这个问题。例如,查看TaskletStep,我发现通常步骤执行看起来像这样:
这似乎有道理。但是2到3之间的失败呢?这意味着业务事务已提交,但Spring Batch无法在其内部元数据中记录该事实。因此重新启动会再次重新处理相同的项目,即使它们已经提交。正确?
我正在寻找对这些细节的解释以及Spring Batch中做出的设计决策的后果。这是在某处记录的吗? Spring Batch参考指南中有很少的细节。它只是从应用程序开发人员的角度解释了一些事情。
答案 0 :(得分:10)
Spring Batch中有两种基本类型的步骤,一个Tasklet步骤和一个基于块的步骤。每个人都有自己的交易细节。让我们看看每个:
基于Tasklet的步骤
当开发人员实现自己的tasklet时,事务性非常简单。每个对Tasklet#execute
方法的调用都在事务中执行。你是正确的,因为在执行步骤逻辑之前和之后都有更新。它们在技术上不包含在事务中,因为回滚不是我们想要支持的作业存储库更新。
基于块的步骤
当开发人员使用基于块的步骤时,由于添加了跳过/重试的能力,因此涉及更多复杂性。但是,从简单的层面来说,每个块都在事务中处理。基于块的步骤之前和之后仍然具有相同的更新,这些更新是非事务性的,原因与前面提到的相同。
"如果"方案强>
在您的问题中,您询问如果业务逻辑已完成但由于某种原因对作业存储库的更新失败会发生什么。是否会在重新启动时重新处理先前更新的项目。在大多数情况下,这取决于。如果您使用有状态的读者/编写者(如FlatFileItemReader
),则每次提交业务事务时,都会使用已处理的当前状态(在同一事务中)更新作业存储库。因此,在这种情况下,重新启动作业将从中断处继续...在这种情况下最后,并且不处理其他记录。
如果你没有使用有状态的读者/作者,或者关闭了保存状态,那么有些买家要小心,你最终可能会遇到你描述的情况。框架中的默认行为是保存状态,以便保留可重启性。