当前位置: 首页 > 知识库问答 >
问题:

使用Spring Boot的Spring批处理-写入错误时永不重试

鲍永春
2023-03-14

我用Spring Boot创建了一个批处理。以下是批处理的主要配置类:

@Configuration
@EntityScan({"my.domain"})
@EnableJpaRepositories({"my.domain"})
@EnableBatchProcessing
public class BatchConfiguration {

    /** Motif d'identification des fichiers d'entrée */
    @Value("${batch.input-file-pattern}")
    private String inputFilePattern;

    @Bean
    public BatchConfigurer configurer( EntityManagerFactory entityManagerFactory ){ 
        return new MapForcedBatchConfigurer( entityManagerFactory ); 
    }

    @Bean
    public Job myJob( JobBuilderFactory jobs, Step step1 ){
        return jobs.get("myJob")
                .incrementer( new RunIdIncrementer() )
                .flow( step1 )
                .end()
                .build();
    }

    @Bean
    public Step step1( StepBuilderFactory stepBuilderFactory, 
            StepExecutionListener stepExecutionListener,
            ItemReader<Input> myReader,
            ItemProcessor<Input, Dto> myProcessor, 
            ItemWriter<Dto> myWriter ){
        return stepBuilderFactory.get("myStep")
                .listener( stepExecutionListener )
                .<Input, Dto> chunk(1)
                .reader( myReader )
                .processor( myProcessor )
                .writer( myWriter )
                .faultTolerant().skipPolicy( new MySkipPolicy() ).retryLimit( 0 )
                .build();
    }

    @Bean
    public StepExecutionListener stepListener() {
        return new MyStepExecutionListener();
    }

    @Bean
    public ItemReader<Input> myReader() throws IOException {
        return new MyItemReader( inputFilePattern );
    }

    @Bean
    public ItemProcessor<Input, Dto> myProcessor(){
        return new MyItemProcessor();
    }

    @Bean
    public ItemWriter<Dto> myWriter(){
        return new MyItemWriter();
    }

}

当处理项目时发生错误,记录器会写入一条消息,然后批处理下一个元素。这正是我想要的。

如果写入操作出错,请重试一次!因此,对于每个写入错误,我有两个错误日志。

如何将批处理配置为无论错误发生在步骤的哪个部分,都不会在出错时重试?

本文解释如下:

[当我们在编写过程中出现跳转时],框架必须找出导致失败的项目。对于缓存的读取项列表中的每个项,它都会启动自己的事务。项目由ItemProcessor处理,然后由ItemWriter写入。如果没有错误,则提交包含一个项目的小区块,并继续迭代下一个项目。我们希望至少有一个可跳过的异常,当这种情况发生时,事务被回滚,该项被标记为跳过项。一旦我们的迭代完成,我们就继续进行正常的块处理。

这可能是对重新执行写入操作的解释。我希望我能以某种方式绕过这种行为。。。

共有2个答案

隆安然
2023-03-14

我认为如果没有子类化FaultTolerantChunkProcessor,你就无能为力。在步骤生成器上调用readeristransacationalqueue()。

原因是Spring Batch试图确定导致错误的项目,即使您的区块只有一个项目,算法也没有考虑到这一点(事实上,为什么要使用大小为1的区块?…)

你能做的就是在你的作者身上捕捉到例外。你甚至可以为这个目的编写一个包装ItemWriter

谷梁嘉运
2023-03-14

我终于想出了一个非常简单的解决办法。我移动了日志和操作,以防标记为@OnSkipInWrite的方法出错。因此,当Spring Batch最终跳过导致错误的元素时,此代码只执行一次。

public class MyItemWriter implements ItemWriter<Dto> {

    @Override
    public void write(List<? extends Dto> items) throws Exception {
        // The writing treatment which may throw a skippable exception...
    }

    @OnSkipInWrite
    public void onSkipInWrite( Dto skippedItem, Exception exception ){
        // Logs, counters, etc.
    }

}

这并不完美,因为抛出异常的处理仍然执行了两次。但我不再有两倍的日志,我的自定义错误计数是正确的。

我仍然对抑制这种“通过小数据块重试一次”行为感兴趣,即使我怀疑这是可能的。

 类似资料:
  • 我按照本教程在Java中配置Spring批处理作业。它通过使用一个接口为多个数据源做准备,然后由每个数据源实现该接口。 这是我目前所掌握的: PostgreSQLConfig.java jobconfig.java 通过对我的MySQLConfig使用注释,我希望使用MySQLConfig bean。相反,我得到的是:

  • 我开始学习spring batch,遇到一个问题,当我想使用在数据库中持久化作业的状态时。编译器显示: “原因:org.springframework.beans.factory.beanCreationException:创建类路径资源[springconfig.xml]中定义的名为'job repository'的bean时出错:调用init方法失败;嵌套异常为java.lang.noClas

  • 在happy path场景中,我有一个spring批处理工作,但现在我将重点放在错误处理上。 但是,在另一个测试中,我想证明一个不可预见的数据库错误会导致作业失败。为此,我创建了一个触发器,该触发器会导致对要插入的表的插入失败。 这似乎起作用了,在writer执行之后,在事务提交期间抛出异常,并且我得到以下日志消息: 这似乎也是预期的行为。问题是,这并不能阻止工作。该步骤退出到SimplyRetr

  • 我试图在spring batch admin中使用mysql数据库,而不是默认的HSQL。根据文件 http://docs.spring.io/spring-batch-admin/reference/reference.xhtml和使用jndi数据源与Spring批处理管理 我复制了to并将其配置值从 到 下面是我的完整配置。 我还尝试应对数据源环境。xml到同一个文件夹,并将其配置更改为mys

  • 我想从mysql读取数据,然后写入sftp。现在我将文件写入本地,从本地写入sftp,最好的方法是什么?