【问题标题】:Spring Batch - How to set chunk > 1 when items have interdependencies?Spring Batch - 当项目具有相互依赖关系时如何设置块> 1?
【发布时间】:2016-12-27 04:03:26
【问题描述】:

我有一个 Spring Batch 作业,需要将所有项目以一个块的形式写入数据库。我想要这种行为,因为

  1. 我需要在写入之前进行一些验证,包括比较读取项之间的比较。
  2. 如果任何验证失败,我需要确保没有任何项目被持久化或所有项目都被持久化。
  3. 这是一个小于 60kb 的少量数据。

该项目是一个Car,它有一个Model 属性。我遇到的问题是项目处理的一部分检查数据库中是否已经存在Model。如果是,它会从数据库中检索模型(包括自动生成的 id),因此不会创建另一个数据库条目。

现在,如果 Model 已经在之前的作业运行中保持不变,那么它可以正常工作。但是,当相同的Model 在同一个作业运行中出现两个不同的Cars 并且Model 之前没有保留时,它会失败。在这种情况下,会为同一个 Model 创建两个数据库行。

我正在使用带有Model 的JPA,其id 属性用@Id@GeneratedValue(strategy = GenerationType.IDENTITY) 注释。在写入之前如何确保相同的Model 不会多次写入数据库?

【问题讨论】:

    标签: java spring hibernate jpa spring-batch


    【解决方案1】:

    我怀疑这种情况正在发生,因为每个块都由一个事务组成,并且您正在对单个事务中的多个元素执行验证和写入,其中一个写入可能会使要写入的另一个项目的验证无效。

    如果你真的想在这种情况下使用面向块的处理,看起来你只需要在你的ItemProcessor 中实现某种缓存解决方案。当您创建一个新的Model 时,您会将该模型的标识符存储在类似Set 的位置。每次处理器处理Car 项目时,它都会检查缓存,然后在创建新模型之前检查数据库中的现有模型。

    否则,您可以通过使用简单的 Tasklet 步骤来完全避免面向块的处理。这样,您就可以完全控制逻辑事务。进行面向块的处理的主要原因是您可以一次编写一大块项目以提高效率。由于您正在对每个项目的数据库进行额外验证,因此您失去了一些好处。

    如果您的Model 表足够小,您可以缓存它,然后在内存中进行所有验证。

    【讨论】:

    • 您能否提供更多关于Takslet 步骤的想法?它会进行读取、处理和写入吗?我不确定ItemProcessor 的缓存解决方案将如何工作。您是否建议 ItemProcessor 保留它在数据库中找到的每个新 Model(在 ItemWriter 之前)? Car 不能有空 Model。如果Model 不为空但有一个空id,它将被视为一个新的ModelModel 表足够小,可以缓存在内存中。谢谢。
    • Tasklet 步骤确实会执行读取、处理和写入操作,但不一定必须遵循该范例。您可以将其视为一种自定义方法,它遍历传入的 Car 元素、验证每个元素并将其持久化,以及新的 Model(如果有的话)。面向块的处理(读取器/处理器/写入器)通常是矫枉过正的,让它处理某些场景有时比它的价值更困难。除非性能导致严重问题,否则您始终可以将块大小保留为 1。
    • 谢谢贾里德。我不能不将块大小保留为 1,因为系统必须保留所有项目(即Cars)或不保留任何项目。它不能只保留一些项目。我不确定Tasklet 对我有什么好处。
    • 另外,我正在使用 JPA。所以,如果Model 没有id,它会在持久化Car 时创建一个新行。由于我必须将所有Cars 保存在一个事务中,因此每个CarModel 将作为数据库中的新行保存(即使Models 相同(即equals() )。经过深思熟虑,我想我现在有几个解决方案。我会发布答案。如果它是一个更好的解决方案,我会接受你的答案,但现在我不确定它会有什么帮助满足要求/解决 OP 中指出的问题。再次感谢您迄今为止的意见。
    【解决方案2】:

    这里有两个解决这个问题的方法:

    1. 创建第一个Step 以读取/处理/写入Models
    2. ItemProcessor<Car> 中,检查Model 是否像当前所做的那样在数据库中。如果它不在数据库中,请在写入所有Cars 之前将其写入数据库。

    选项 1 的缺点是:1) 文件被读取两次(一次用于Models,一次用于Cars)。 2) 如果Car 步骤失败,您可能拥有Models,但没有关联的Cars。

    选项 2 将涉及对数据库的更多命中。但是,记录的数量很少。此外,对 DB 的 Model 写入与所有 Cars 的写入在同一事务中。因此,如果Cars 无法持续​​存在,其关联的Models 也会持续存在。

    【讨论】:

      猜你喜欢
      • 2018-01-09
      • 1970-01-01
      • 2015-11-02
      • 1970-01-01
      • 2016-08-14
      • 1970-01-01
      • 2021-02-21
      • 1970-01-01
      • 2011-07-07
      相关资源
      最近更新 更多