Spring batch 当ItemWriter中发生异常时,如何防止回滚?

Spring batch 当ItemWriter中发生异常时,如何防止回滚?,spring-batch,Spring Batch,我们的编写器设计用于将记录写入关系数据库。 如果任何记录发生异常,Spring Batch将对区块中的每条记录执行回滚并重试写入操作。这导致发生SQL重复密钥异常,因为区块中先前处理的记录已成功写入数据库 我们已经尝试使用noRetry()和noRollback(),显式地指定了不应触发重试或回滚的异常列表 根据Spring Batch在线文档,当ItemWriter发生错误时,可以使用noRollback()来防止回滚: 但是,这与源代码中的java文档相矛盾,源代码中说在写入过程中忽略Fau

我们的编写器设计用于将记录写入关系数据库。 如果任何记录发生异常,Spring Batch将对区块中的每条记录执行回滚并重试写入操作。这导致发生SQL重复密钥异常,因为区块中先前处理的记录已成功写入数据库

我们已经尝试使用noRetry()和noRollback(),显式地指定了不应触发重试或回滚的异常列表

根据Spring Batch在线文档,当ItemWriter发生错误时,可以使用noRollback()来防止回滚:

但是,这与源代码中的java文档相矛盾,源代码中说在写入过程中忽略FaultTolerantStepBuilder.noRollback()

以下是我们的工作定义示例:

    @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;
            }
        };
    }
@Bean(“我的工作”)
公共职务职务(步骤){
return jobBuilderFactory.get(“我的工作”)
.开始(步骤)
.build();
}
@豆子
公共步骤(){
返回stepBuilderFactory.get(“跳过步骤”)
.chunk(3)
.reader(reader())
.processor(myprocessor())
.writer(this::write)
.容错()
.skipLimit(1)
.skip(JobSkipableException.class)
.noRollback(JobSkippableException.class)
.noRetry(JobSkipableException.class)
.processorNonTransactional()
.build();
}
公共项目阅读器(){
返回新的ItemReader(){
@凌驾
public String read()引发异常、UnexpectedInputException、ParseException、NonTransientResourceException{
字符串s=randomUUID().toString();
debug(“读取字符串{}”,s);
返回s;
}
};
}

public void write(List不是一个解决方案,但至少是一个解释,解释了为什么框架的行为不像我在
FaultTolerantChunkProcessor
的第335-350行中看到的那样:

                    try {
                        doWrite(outputs.getItems());
                    }
                    catch (Exception e) {
                        if (rollbackClassifier.classify(e)) {
                            throw e;
                        }
                        /*
                         * If the exception is marked as no-rollback, we need to
                         * override that, otherwise there's no way to write the
                         * rest of the chunk or to honour the skip listener
                         * contract.
                         */
                        throw new ForceRollbackForWriteSkipException(
                                "Force rollback on skippable exception so that skipped item can be located.", e);                   }
可能的重复可能的重复