【问题标题】:How to know which chunk has failed in Spring Batch and assign Counter value?如何知道 Spring Batch 中哪个块失败并分配 Counter 值?
【发布时间】:2021-02-11 08:32:07
【问题描述】:

我在这里扩展这个问题 - Identify which chunk has failed in chunk based step in Spring Batch

你能告诉我下面的代码吗?

  1. 如何知道哪个块失败了?
  2. 如何创建一个计数器并将自动递增的值分配给一个非 PK 字段并保存到 DB?

【问题讨论】:

  • 一个块不会只失败该块的 1 个或多个项目。要确定哪些项目失败,您可以使用SkipListener。正如在其他问题中已经回答的那样。
  • @M.Deinum - 我已经实现了 SkipListener 但我需要得到哪个块失败了......我们怎样才能得到它?我这里不需要物品
  • 如前所述,块不会只失败单个项目。

标签: spring spring-batch


【解决方案1】:

在非容错步骤中,任何块中的第一个错误都会使该步骤失败,您可以在ChunkListener 实现中使用计数器获取块编号,如previously 所述。这是一个简单的例子:

import java.util.Arrays;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
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.core.listener.ChunkListenerSupport;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.item.support.ListItemReader;
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 MyJobConfiguration {

    @Bean
    public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) {
        return jobs.get("job")
                .start(steps.get("step")
                        .<Integer, Integer>chunk(5)
                        .reader(new ListItemReader<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)))
                        .writer(items -> {
                            System.out.println("About to write items " + items);
                            if (items.contains(8)) {
                                throw new Exception("No 8 here!");
                            }
                        })
                        .listener(new MyChunkListener())
                        .build())
                .build();
    }

    static class MyChunkListener extends ChunkListenerSupport {
        private int counter;

        @Override
        public void beforeChunk(ChunkContext context) {
            counter++;
        }

        @Override
        public void afterChunkError(ChunkContext context) {
            System.out.println("Chunk number " + counter + " failed");
        }
    }

    public static void main(String[] args) throws Exception {
        ApplicationContext context = new AnnotationConfigApplicationContext(MyJobConfiguration.class);
        JobLauncher jobLauncher = context.getBean(JobLauncher.class);
        Job job = context.getBean(Job.class);
        jobLauncher.run(job, new JobParameters());
    }

}

打印出来:

About to write items [1, 2, 3, 4, 5]
About to write items [6, 7, 8, 9, 10]
Chunk number 2 failed

但是,在容错步骤中,项目将被一个一个重试,Spring Batch 将创建单个项目块。在这种情况下,ChunkListener 将为这些单项块中的每一个调用,因此应该正确解释计数器。这是上一个示例的容错版本:

import java.util.Arrays;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
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.core.listener.ChunkListenerSupport;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.item.support.ListItemReader;
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 MyJobConfiguration {

    @Bean
    public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) {
        return jobs.get("job")
                .start(steps.get("step")
                        .<Integer, Integer>chunk(5)
                        .faultTolerant()
                        .skip(Exception.class)
                        .skipLimit(10)
                        .reader(new ListItemReader<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)))
                        .writer(items -> {
                            System.out.println("About to write items " + items);
                            if (items.contains(8)) {
                                throw new Exception("No 8 here!");
                            }
                        })
                        .listener(new MyChunkListener())
                        .build())
                .build();
    }

    static class MyChunkListener extends ChunkListenerSupport {
        private int counter;

        @Override
        public void beforeChunk(ChunkContext context) {
            counter++;
        }

        @Override
        public void afterChunkError(ChunkContext context) {
            System.out.println("Chunk number " + counter + " failed");
        }
    }

    public static void main(String[] args) throws Exception {
        ApplicationContext context = new AnnotationConfigApplicationContext(MyJobConfiguration.class);
        JobLauncher jobLauncher = context.getBean(JobLauncher.class);
        Job job = context.getBean(Job.class);
        jobLauncher.run(job, new JobParameters());
    }

}

哪个打印:

About to write items [1, 2, 3, 4, 5]
About to write items [6, 7, 8, 9, 10]
Chunk number 2 failed
About to write items [6]
About to write items [7]
About to write items [8]
Chunk number 5 failed
About to write items [9]
About to write items [10]

【讨论】:

  • 谢谢,您也可以帮忙解决这个问题 - “如何制作一个计数器并将自动递增的值分配给一个不是 PK 的字段并保存到数据库?”
  • 你这是什么意思?是否要将计数器值保存在 DB 中?请详细说明您到底想要什么。
  • 如果我从 DB 读取 1000 条记录,那么我需要将自动增量值设置为 src_row_num 字段,该字段是来自 Employee 的字段,Employee1 应该有 src_row_num=1,Employee2 应该有 src_row_num=2,Employee3 应该有 src_row_num=3 等等。
  • 这与您最初关于如何识别哪个块失败的问题有什么关系?您在此处描述的是为当前项目分配 ROW_ID。那是另一回事,可以使用ItemReadListener#afterRead 来完成,您可以在其中为当前项目分配一个自动递增的值。
  • 这在JobRestart的情况下不起作用,你说什么?
猜你喜欢
  • 1970-01-01
  • 2021-06-10
  • 1970-01-01
  • 1970-01-01
  • 2015-06-18
  • 1970-01-01
  • 1970-01-01
  • 2018-02-05
  • 2020-12-09
相关资源
最近更新 更多