Spring boot @在SkipListener中未调用OnSkipInWrite

Spring boot @在SkipListener中未调用OnSkipInWrite,spring-boot,spring-data-jpa,spring-batch,Spring Boot,Spring Data Jpa,Spring Batch,我正在读取csv文件,并使用spring批处理(读取、处理和写入)将数据插入数据库。我正在itemWriter类中使用“jpaRepository.save”将数据保存到数据库中。我试图在@OnSkipInWrite方法中捕获跳过的项和跳过的消息,但即使跳过了数据,也不会调用此方法。在批处理步骤执行表中: 读取计数=18,写入计数=10,写入跳过计数=0,回滚计数=8。 为什么写入跳过计数为0?我只想知道跳过了哪个项目,以及异常消息是什么。我的步骤: @Bean public Step step

我正在读取csv文件,并使用spring批处理(读取、处理和写入)将数据插入数据库。我正在itemWriter类中使用“jpaRepository.save”将数据保存到数据库中。我试图在@OnSkipInWrite方法中捕获跳过的项和跳过的消息,但即使跳过了数据,也不会调用此方法。在批处理步骤执行表中: 读取计数=18,写入计数=10,写入跳过计数=0,回滚计数=8。 为什么写入跳过计数为0?我只想知道跳过了哪个项目,以及异常消息是什么。我的步骤:

@Bean
public Step step() throws IOException {
    return stepBuilderFactory.get("step").<Entity, Entity>chunk(1).reader(multiResourceItemReader())
            .processor(processor()).writer(writer()).faultTolerant().skip(Exception.class).skipLimit(100)
            .listener(new stepExecutionListener()).build();
}
@Bean
公共步骤步骤()引发IOException{
返回stepBuilderFactory.get(“step”).chunk(1.reader(multiResourceItemReader())
.processor(processor()).writer(writer()).faultTolerant().skip(Exception.class).skipLimit(100)
.listener(新的stepExecutionListener()).build();
}
这是我的听众课

     public class StepExecutionListener{

private static final Logger LOG = Logger.getLogger(StepExecutionListener.class);

@OnSkipInRead
public void onSkipInRead(Throwable t) {
    LOG.error("On Skip in Read Error : " + t.getMessage());
}

@OnSkipInWrite
public void onSkipInWrite(Entity item, Throwable t) {
    LOG.error("Skipped in write due to : " + t.getMessage());
}

@OnSkipInProcess
public void onSkipInProcess(Entity item, Throwable t) {
    LOG.error("Skipped in process due to: " + t.getMessage());
}

@OnWriteError
public void onWriteError(Exception exception, List<? extends Entity> items) {
    LOG.error("Error on write on " + items + " : " + exception.getMessage());
}}
公共类StepExecutionListener{
私有静态最终记录器LOG=Logger.getLogger(StepExecutionListener.class);
@昂斯基平雷德
公共无效OnSkipRead(可丢弃的t){
LOG.error(“在读取错误中跳过:+t.getMessage());
}
@OnSkipInWrite
公共无效onSkipInWrite(实体项,可丢弃的t){
LOG.error(“由于:“+t.getMessage()”,写入时跳过);
}
@Onskipin过程
公共无效onSkipInProcess(实体项,可丢弃的t){
LOG.error(“由于:“+t.getMessage()”,在进程中被跳过);
}
@书写错误

public void onWriteError(异常,List从您共享的内容中,我看不出为什么不调用跳过侦听器,但下面是一个使用您的侦听器的自包含示例:

import java.util.Arrays;
import java.util.List;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.annotation.OnSkipInProcess;
import org.springframework.batch.core.annotation.OnSkipInRead;
import org.springframework.batch.core.annotation.OnSkipInWrite;
import org.springframework.batch.core.annotation.OnWriteError;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.support.ListItemReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableBatchProcessing
public class MyJob {

    @Autowired
    private JobBuilderFactory jobs;

    @Autowired
    private StepBuilderFactory steps;

    @Bean
    public ItemReader<Integer> itemReader() {
        return new ListItemReader<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
    }

    @Bean
    public ItemWriter<Integer> itemWriter() {
        return items -> {
            for (Integer item : items) {
                if (item.equals(3)) {
                    throw new Exception("No 3 here!");
                }
                System.out.println("item = " + item);
            }
        };
    }

    @Bean
    public Step step() {
        return steps.get("step")
                .<Integer, Integer>chunk(5)
                .reader(itemReader())
                .writer(itemWriter())
                .faultTolerant()
                .skip(Exception.class)
                .skipLimit(10)
                .listener(new StepExecutionListener())
                .build();
    }

    @Bean
    public Job job() {
        return jobs.get("job")
                .start(step())
                .build();
    }

    public class StepExecutionListener {

        @OnSkipInRead
        public void onSkipInRead(Throwable t) {
            System.err.println("On Skip in Read Error : " + t.getMessage());
        }

        @OnSkipInWrite
        public void onSkipInWrite(Integer item, Throwable t) {
            System.err.println("Skipped in write due to : " + t.getMessage());
        }

        @OnSkipInProcess
        public void onSkipInProcess(Integer item, Throwable t) {
            System.err.println("Skipped in process due to: " + t.getMessage());
        }

        @OnWriteError
        public void onWriteError(Exception exception, List<? extends Integer> items) {
            System.err.println("Error on write on " + items + " : " + exception.getMessage());
        }}

    public static void main(String[] args) throws Exception {
        ApplicationContext context = new AnnotationConfigApplicationContext(MyJob.class);
        JobLauncher jobLauncher = context.getBean(JobLauncher.class);
        Job job = context.getBean(Job.class);
        JobExecution jobExecution = jobLauncher.run(job, new JobParameters());
        StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next();
        System.out.println("WriteSkipCount = " + stepExecution.getWriteSkipCount());
    }

}
这意味着在写入时跳过项目并且
writeSkipCount
正确时,将调用跳过侦听器


希望这有帮助。

您可以实现SkipListener接口,而不是使用@OnWriteError注释。

在您的BatchConf中尝试:

@Bean
@StepScope
public StepExecutionListener stepExecutionListener() {
    return new StepExecutionListener();
}
。。。 .skipLimit(1) .listener(stepExecutionListener()

.build();

sprngbatch跳过的最佳示例
@Bean
@StepScope
public StepExecutionListener stepExecutionListener() {
    return new StepExecutionListener();
}