Spring Batch跳过策略疑问:首次执行失败后才正常?
场景描述
我有3条数据,Chunk size设置为3:
- 数据a:存在错误,属于失败场景
- 数据b:可成功插入
- 数据c:存在错误,属于失败场景
未配置跳过策略时,写入器执行插入操作时三条数据均未成功插入,任务失败。之后实现Skip Policy后任务变为成功,会跳过失败项继续处理后续数据。但首次执行时仍会导致整个事务失败,第二次执行才完全正常,请问这是Spring Batch的固有特性吗?
代码配置
@Bean public Step step(WriterListener writerListener) { return stepBuilderFactory.get("step").<TransactionDetail, Tbl>chunk(chunk) .reader(reader).processor(processor) .writer(writer(datasource)).faultTolerant().skipPolicy(skipPolicy()).listener(writerListener).build(); } @Bean public JobSkipPolicy skipPolicy() { return new JobSkipPolicy(); }
疑问解答
1. 首次执行事务失败是Spring Batch的固有特性吗?
这是Spring Batch的固有特性。核心原因在于Chunk处理的事务机制:
当Chunk中存在失败项时,首次执行整个Chunk的写入操作会抛出异常,导致事务回滚。此时Spring Batch的容错机制会被触发——它会将原Chunk拆分为单个条目重新处理,对每个条目单独执行写入逻辑,跳过符合Skip Policy的失败项,确保可成功的数据被正确写入。
第二次执行时,因为失败项已被标记为跳过,Chunk处理无异常,事务正常提交,所以表现完全正常。首次的事务失败是容错流程的必要环节,Spring Batch需要先检测到整体Chunk的失败,再通过拆分重试/跳过的方式完成部分数据的写入。
2. 首次执行触发onWriteError()是否符合预期?
这种触发行为是符合预期的。
首次执行时,整个Chunk的写入操作因包含失败项而抛出异常,会触发onWriteError()(对应整个Chunk写入失败的回调)。而当Spring Batch拆分条目重新处理时,成功的条目(数据b)会单独触发onWrite(),失败的条目(a、c)会触发onWriteError()(单个条目写入失败的回调)。你看到的首次onWriteError()是整体Chunk失败的回调,后续拆分处理的细粒度回调可能被忽略了。
如果需要更精准地监听单个条目的写入状态,可以利用ItemWriteListener的onWriteError(Exception exception, List<? super T> items)方法,其中items参数会包含本次写入失败的具体条目,以此区分失败项;成功条目在单独处理时会正常触发onWrite(List<? super T> items)。
内容的提问来源于stack exchange,提问作者Developer

