Spring Batch - 如何设置chunk> 1当物品有相互依赖关系时?

时间:2016-08-19 22:20:31

标签: java spring hibernate jpa spring-batch

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

  1. 我需要做一些验证,包括在写作之前比较读取项目。
  2. 如果任何验证失败,我需要确保没有项目持久存在或所有项目都是持久的。
  3. 它是一小部分数据< 60KB。
  4. 该项目为Car,并且具有Model属性。我遇到的问题是项目处理的一部分检查数据库中是否已存在Model。如果是,它将从DB检索模型(包括自动生成的id),因此不会创建另一个DB条目。

    现在,如果Model已在先前的作业运行中保留,则可以正常工作。但是,如果同一Model在同一作业中显示两个不同的Car并且先前未保留Model,则会失败。在这种情况下,将为同一Model创建两个数据库行。

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

2 个答案:

答案 0 :(得分:1)

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

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

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

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

答案 1 :(得分:0)

以下两个选项可以解决此问题:

  1. 创建第一个Step来阅读/处理/写入Model s
  2. ItemProcessor<Car>中,检查当前正在执行的Model是否在数据库中。如果它不在数据库中,请在写入所有Car之前将其写入数据库。
  3. 选项1的缺点是:1)文件被读取两次(Model一次,Car一次)。 2)如果Car步骤失败,您可以Model个没有关联的Car

    选项2将涉及更多数据库命中。但是,记录数量很少。此外,对{DB}的Model写入与所有Car的写入处于同一事务中。因此,如果Car未能保持,那么它的相关Model s。