我有一个Spring Batch作业,需要在一个块中将所有项目写入数据库。我想要这种行为,因为
该项目为Car
,并且具有Model
属性。我遇到的问题是项目处理的一部分检查数据库中是否已存在Model
。如果是,它将从DB检索模型(包括自动生成的id),因此不会创建另一个DB条目。
现在,如果Model
已在先前的作业运行中保留,则可以正常工作。但是,如果同一Model
在同一作业中显示两个不同的Car
并且先前未保留Model
,则会失败。在这种情况下,将为同一Model
创建两个数据库行。
我使用带有Model
的JPA,其id属性标注为@Id
和@GeneratedValue(strategy = GenerationType.IDENTITY)
。如何在写入之前确保相同的Model
不会多次写入数据库?
答案 0 :(得分:1)
我怀疑这种情况正在发生,因为每个块都包含一个事务,并且您正在为该单个事务中的多个元素执行验证和写入,并且其中一个写入可能使另一个项目的验证无效写入。
如果你真的想在这种情况下使用面向块的处理,你似乎只需要在ItemProcessor
中实现某种缓存解决方案。当您创建新的Model
时,您会将该模型的标识符存储为Set
之类的内容。每次处理器处理Car
项时,它都会检查缓存,然后在创建新模型之前检查数据库中的现有模型。
否则,您可以完全通过使用简单的Tasklet步骤来避免面向块的处理。有了这个,您就可以完全控制逻辑事务。进行面向块的处理的主要原因是,您可以一次编写大量项目以提高效率。由于您正在为每个项目对数据库进行额外验证,因此您将失去一些好处。
如果您的Model
表足够小,您可以对其进行缓存,然后在内存中进行所有验证。
答案 1 :(得分:0)
以下两个选项可以解决此问题:
Step
来阅读/处理/写入Model
s ItemProcessor<Car>
中,检查当前正在执行的Model
是否在数据库中。如果它不在数据库中,请在写入所有Car
之前将其写入数据库。选项1的缺点是:1)文件被读取两次(Model
一次,Car
一次)。 2)如果Car
步骤失败,您可以Model
个没有关联的Car
。
选项2将涉及更多数据库命中。但是,记录数量很少。此外,对{DB}的Model
写入与所有Car
的写入处于同一事务中。因此,如果Car
未能保持,那么它的相关Model
s。