如何在出现异常的情况下重写委托编写器的Spring Batch CompositeItemWriter管理事务? [英] How to override Spring Batch CompositeItemWriter manage transaction for delegate writers in case of exception arises?
问题描述
我在此扩展此How does Spring Batch CompositeItemWriter manage transaction for delegate writers?问题:
在我的示例中,我有一个下面的CompositeItemWriter
,它将数据写入同一数据库的多个表中,在写入数据之前,它通过实现各种业务规则来转换数据。在这里,一条记录可能满足不同的业务规则等。因此,一个写入者可能比其他写入者获得更多数据。
@Bean
public CompositeItemWriter<Employee> EmployeeCompositeWriter() throws Exception {
List<ItemWriter<? super Employee>> employee = new ArrayList<>();
employee.add(employeeWriter());
employee.add(departmentWriter());
employee.add(stockWriter());
employee.add(purchaseWriter());
CompositeItemWriter<Employee> compositeItemWriter = new CompositeItemWriter<>();
compositeItemWriter.setDelegates(employee);
compositeItemWriter.afterPropertiesSet();
return compositeItemWriter;
}
方案-假设第一个编写器工作得很好,第二个编写器生成异常,然后第三个和第四个编写器不会被调用,这是由于事务回滚而导致的Spring批处理中Automic
性质的默认值。
这里即使第二个Writer出现异常,我也想成功调用第三个Writer和第四个Writer并保存数据,我也想成功保存第一个Writer和第二个Writer的数据。仅希望在SkipListener
的帮助下将异常数据存储到错误表中,以识别哪些记录是垃圾记录。
解决方案-为实现上述方案,我们在每个编写器写入方法上添加了@Transactional(propagation = Propagation.REQUIRES_NEW)
,第一个编写器现在保存数据,第二个编写器生成异常(使用namedJdbcTemplate.batchUpdate()
批量更新数据)我们正在缓存它并重新抛出它,但我们可以看到提交级别降至1(偏离了识别Exact垃圾记录的路线),并且当第二个编写器再次出现异常时,第一个编写器被调用,它正在保存重复的数据和编写器
在这里,如果单个或几个记录是垃圾记录,我不希望整个批处理作业停止,因为此作业对于我们每次都要运行至关重要。有没有办法保存所有不出现异常的数据,如果可能的话,只用SkipListener
或者其他方式将异常数据保存到错误表中?
如果我们可以将批处理组件(如任何步骤的(读取器或处理器)部分)重用到另一个步骤中,是否有任何方法?
推荐答案
问题的主要根本原因是,我们试图使用两个不同的ItemWriter
将数据写入同一个表,这会导致事务行为异常。
我们实现了SkipListenets
(考虑到在初始数据加载时执行验证时,用户可能不会经常获得垃圾或垃圾数据)。
由于我们在批处理作业中实现了"Spring批量跳过技术",这有助于我们指定某些异常类型和最大数量。跳过的项,并且每当抛出其中一个可跳过的异常时,批处理作业不会失败,而是跳过该特定项并转到下一项。仅当最大否。达到跳过的项目数时,批处理作业将失败。我们已经将跳过逻辑与Spring Batch的"容错"功能一起应用于面向块的步骤中的项目,而不是整个步骤。
因此,如果项目在一个委派处写入失败,则对于所有其他委派,它将被视为失败(该项目将不会传递给其他委派),我们可以接受它,因为我们在错误日志表中捕获了详细信息,并且可以在需要时从那里重新处理它。
这篇关于如何在出现异常的情况下重写委托编写器的Spring Batch CompositeItemWriter管理事务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!