【发布时间】:2020-01-07 15:36:10
【问题描述】:
我们的编写器旨在将记录写入关系数据库。 如果任何记录发生异常,Spring Batch 会对块中的每条记录执行回滚和重试写入操作。这会导致发生 SQL Duplicate Key 异常,因为块中先前处理的记录已成功写入数据库。
我们尝试使用 noRetry() 和 noRollback(),明确指定不应触发重试或回滚的异常列表。
根据 Spring Batch 在线文档 noRollback() 可用于在 ItemWriter 发生错误时防止回滚:https://docs.spring.io/spring-batch/4.1.x/reference/html/step.html#controllingRollback
然而,这与源代码中的 java doc 相矛盾,java doc 在写入过程中会忽略 FaultTolerantStepBuilder.noRollback(): https://docs.spring.io/spring-batch/4.1.x/api/index.html?org/springframework/batch/core/step/builder/FaultTolerantStepBuilder.html
这是我们的 Job 定义示例:
@Bean("my-job")
public Job job(Step step) {
return jobBuilderFactory.get("my-job")
.start(step)
.build();
}
@Bean
public Step step() {
return stepBuilderFactory.get("skip-step")
.<String, String>chunk(3)
.reader(reader())
.processor(myprocessor())
.writer(this::write)
.faultTolerant()
.skipLimit(1)
.skip(JobSkippableException.class)
.noRollback(JobSkippableException.class)
.noRetry(JobSkippableException.class)
.processorNonTransactional()
.build();
}
public ItemReader<String> reader() {
return new ItemReader<String> () {
@Override
public String read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
String s = randomUUID().toString();
logger.debug("READ STRING {}", s);
return s;
}
};
}
public void write(List<? extends String> items) {
for(String s : items) {
logger.debug("WRITE STRING {}", s);
throw new JobSkippableException("My skippable exception");
}
}
public ItemProcessor <String, String> myprocessor() {
return new ItemProcessor<String, String>() {
@Override
public String process(String item) throws Exception {
logger.debug("PROCESS STRING {}", item);
return item;
}
};
}
我们的预期行为是 write 中发生的异常不会触发重试或回滚。这将防止重复调用数据库,因此不会导致 SQL Duplicate Key 异常。
【问题讨论】:
标签: spring-batch