Spring

Spring Batch Tasklet, Chunks 차이 및 예제

기록만이살길 2020. 6. 24. 01:49
반응형

Spring Batch Tasklet, Chunks 차이 및 예제

1. 소개

스프링 배치 는 작업을 구현하기위한 두 가지 다른 방법을 제공합니다 : 태스크 릿과 청크 사용 .

이 기사에서는 간단한 실제 예제를 사용하여 두 가지 방법을 구성하고 구현하는 방법을 배웁니다.

2. 의존성

필요한 의존성추가하여 시작하자 :

<dependency>
    <groupId>org.springframework.batch</groupId>
    <artifactId>spring-batch-core</artifactId>
    <version>4.2.0.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.batch</groupId>
    <artifactId>spring-batch-test</artifactId>
    <version>4.2.0.RELEASE</version>
    <scope>test</scope>
</dependency>

스프링 배치 코어스프링 배치 테스트 의 최신 버전을 얻으려면 Maven Central을 참조하십시오.

3. 우리의 사용 사례

다음 내용이 포함 된 CSV 파일을 고려하십시오.

Mae Hodges,10/22/1972
Gary Potter,02/22/1953
Betty Wise,02/17/1968
Wayne Rose,04/06/1977
Adam Caldwell,09/27/1995
Lucille Phillips,05/14/1992

각 줄첫 번째 위치는 사람의 이름을 나타내고 두 번째 위치는 그 / 그녀의 생년월일을 나타냅니다 .

우리의 사용 사례는 각 사람의 이름과 나이를 포함하는 다른 CSV 파일생성하는 것입니다 .

Mae Hodges,45
Gary Potter,64
Betty Wise,49
Wayne Rose,40
Adam Caldwell,22
Lucille Phillips,25

도메인이 명확 해지면 두 가지 방법을 모두 사용하여 솔루션을 구축해 보겠습니다. 태스크 릿부터 시작하겠습니다.

4. Tasklets 방식

4.1. 소개 및 디자인

태스크 릿은 단계 내에서 단일 태스크를 수행하기위한 것입니다. 우리의 임무는 차례대로 실행되는 여러 단계로 구성됩니다. 각 단계는 하나의 정의 된 작업 만 수행해야합니다 .

우리의 일은 세 단계로 구성됩니다.

  1. 입력 CSV 파일에서 행을 읽습니다.
  2. 입력 CSV 파일에서 모든 사람의 나이를 계산하십시오.
  3. 각 사람의 이름과 나이를 새 출력 CSV 파일에 씁니다.

큰 그림이 준비되었으므로 단계 당 하나의 클래스를 만들어 봅시다.

LinesReader 는 입력 파일에서 데이터 읽기를 담당합니다.

public class LinesReader implements Tasklet {
    // ...
}

LinesProcessor 는 파일에있는 모든 사람의 나이를 계산합니다.

public class LinesProcessor implements Tasklet {
    // ...
}

마지막으로 LinesWriter 는 출력 파일에 이름과 연령을 기록 할 책임이 있습니다.

public class LinesWriter implements Tasklet {
    // ...
}

이 시점에서 모든 단계는 Tasklet 인터페이스를 구현 합니다. 이를 통해 우리는 execute 메소드 를 구현 해야 합니다.

@Override
public RepeatStatus execute(StepContribution stepContribution, 
  ChunkContext chunkContext) throws Exception {
    // ...
}

이 방법은 각 단계에 대한 논리를 추가하는 곳입니다. 해당 코드로 시작하기 전에 작업을 구성하겠습니다.

4.2. 구성

Spring의 애플리케이션 컨텍스트에 구성추가 해야합니다 . 이전 섹션에서 생성 된 클래스에 대한 표준 Bean 선언을 추가 한 후 작업 정의를 작성할 준비가되었습니다.

@Configuration
@EnableBatchProcessing
public class TaskletsConfig {

    @Autowired
    private JobBuilderFactory jobs;

    @Autowired
    private StepBuilderFactory steps;

    @Bean
    protected Step readLines() {
        return steps
          .get("readLines")
          .tasklet(linesReader())
          .build();
    }

    @Bean
    protected Step processLines() {
        return steps
          .get("processLines")
          .tasklet(linesProcessor())
          .build();
    }

    @Bean
    protected Step writeLines() {
        return steps
          .get("writeLines")
          .tasklet(linesWriter())
          .build();
    }

    @Bean
    public Job job() {
        return jobs
          .get("taskletsJob")
          .start(readLines())
          .next(processLines())
          .next(writeLines())
          .build();
    }

    // ...

}

이는 *"taskletsJob"* 이 세 단계로 구성됨을 의미 합니다. 첫 번째 ( readLines )는 Bean linesReader에 정의 된 태스크 릿을 실행 하고 다음 단계 인 processLines 로 이동합니다 . ProcessLines 는 Bean linesProcessor에 정의 된 태스크 릿을 수행하고 마지막 단계 인 writeLines 로 이동합니다 .

작업 흐름이 정의되었으며 로직을 추가 할 준비가되었습니다!

4.3. 모델과 활용

CSV 파일에서 줄을 조작 할 때 클래스 을 만들 것입니다 .

public class Line implements Serializable {

    private String name;
    private LocalDate dob;
    private Long age;

    // standard constructor, getters, setters and toString implementation

}

제발 참고 라인이 구현 직렬화합니다. 이는 Line 이 단계간에 데이터를 전송하기위한 DTO 역할을 하기 때문 입니다. 스프링 배치에 따르면, 단계 사이에 전송되는 객체는 직렬화 가능해야합니다 .

반면에, 우리는 글을 읽고 쓰는 것에 대해 생각할 수 있습니다.

이를 위해 OpenCSV를 사용합니다.

<dependency>
    <groupId>com.opencsv</groupId>
    <artifactId>opencsv</artifactId>
    <version>4.1</version>
</dependency>

Maven Central에서 최신 OpenCSV 버전을 찾으십시오 .

OpenCSV가 포함되면 FileUtils 클래스도 만들 것 입니다. CSV 행을 읽고 쓰는 방법을 제공합니다.

public class FileUtils {

    public Line readLine() throws Exception {
        if (CSVReader == null) 
          initReader();
        String[] line = CSVReader.readNext();
        if (line == null) 
          return null;
        return new Line(
          line[0], 
          LocalDate.parse(
            line[1], 
            DateTimeFormatter.ofPattern("MM/dd/yyyy")));
    }

    public void writeLine(Line line) throws Exception {
        if (CSVWriter == null) 
          initWriter();
        String[] lineStr = new String[2];
        lineStr[0] = line.getName();
        lineStr[1] = line
          .getAge()
          .toString();
        CSVWriter.writeNext(lineStr);
    }

    // ...
}

공지 사항 것을 내의 readLine는 OpenCSV의에 대한 래퍼 역할을 readNext의 방법 및 반환 라인 개체를.

같은 방법으로, writeLine은 OpenCSV의 writeNextLine 객체로받습니다. 이 클래스의 전체 구현은 GitHub 프로젝트 에서 찾을 수 있습니다 .

이 시점에서 우리는 모든 단계 구현으로 시작하도록 설정되었습니다.

4.4. Tasklet Lines Reader구성

계속해서 LinesReader 클래스를 완성 해 봅시다 :

public class LinesReader implements Tasklet, StepExecutionListener {

    private final Logger logger = LoggerFactory
      .getLogger(LinesReader.class);

    private List<Line> lines;
    private FileUtils fu;

    @Override
    public void beforeStep(StepExecution stepExecution) {
        lines = new ArrayList<>();
        fu = new FileUtils(
          "taskletsvschunks/input/tasklets-vs-chunks.csv");
        logger.debug("Lines Reader initialized.");
    }

    @Override
    public RepeatStatus execute(StepContribution stepContribution, 
      ChunkContext chunkContext) throws Exception {
        Line line = fu.readLine();
        while (line != null) {
            lines.add(line);
            logger.debug("Read line: " + line.toString());
            line = fu.readLine();
        }
        return RepeatStatus.FINISHED;
    }

    @Override
    public ExitStatus afterStep(StepExecution stepExecution) {
        fu.closeReader();
        stepExecution
          .getJobExecution()
          .getExecutionContext()
          .put("lines", this.lines);
        logger.debug("Lines Reader ended.");
        return ExitStatus.COMPLETED;
    }
}

LinesReader의 execute 메소드 는 입력 파일 경로를 통해 FileUtils 인스턴스를 작성합니다 . 그런 다음 읽을 행이 더 이상 없을 때까지 목록에 행을 추가합니다 .

우리 클래스 는 또한 StepStepuumentListener구현 하여 두 가지 추가 메소드 인 beforeStepafterStep을 제공 합니다. 우리는이 메소드를 사용하여 실행 실행 전후에 초기화하고 닫습니다 .

afterStep 코드 를 살펴보면 다음 단계에서 사용할 수 있도록 결과 목록 ( 행) 이 작업 컨텍스트에있는 행을 확인할 수 있습니다.

stepExecution
  .getJobExecution()
  .getExecutionContext()
  .put("lines", this.lines);

이 시점에서 첫 번째 단계는 이미 책임을 수행했습니다. CSV 행을 메모리 의 목록 에 로드 합니다. 두 번째 단계로 이동하여 처리하겠습니다.

4.5. Tasklet Lines Processor 구성

LinesProcessorStepExecutionListenerTasklet 도 구현할 것 입니다. 즉, beforeStep , executeafterStep 메소드도구현합니다.

public class LinesProcessor implements Tasklet, StepExecutionListener {

    private Logger logger = LoggerFactory.getLogger(
      LinesProcessor.class);

    private List<Line> lines;

    @Override
    public void beforeStep(StepExecution stepExecution) {
        ExecutionContext executionContext = stepExecution
          .getJobExecution()
          .getExecutionContext();
        this.lines = (List<Line>) executionContext.get("lines");
        logger.debug("Lines Processor initialized.");
    }

    @Override
    public RepeatStatus execute(StepContribution stepContribution, 
      ChunkContext chunkContext) throws Exception {
        for (Line line : lines) {
            long age = ChronoUnit.YEARS.between(
              line.getDob(), 
              LocalDate.now());
            logger.debug("Calculated age " + age + " for line " + line.toString());
            line.setAge(age);
        }
        return RepeatStatus.FINISHED;
    }

    @Override
    public ExitStatus afterStep(StepExecution stepExecution) {
        logger.debug("Lines Processor ended.");
        return ExitStatus.COMPLETED;
    }
}

작업 컨텍스트에서 목록을 로드 하고 각 사람의 나이를 계산 한다는 것을 이해하는 것은 쉽지 않습니다.

이전 단계에서 온 동일한 오브젝트에서 수정이 발생하므로 컨텍스트에 다른 결과 목록을 넣을 필요가 없습니다.

그리고 우리는 마지막 단계에 대한 준비가되었습니다.

4.6. Tasklet LinesWriter 구성

LinesWriter 의 임무는 목록 을 살펴 보고 출력 파일에 이름과 나이를 쓰는 것입니다 .

public class LinesWriter implements Tasklet, StepExecutionListener {

    private final Logger logger = LoggerFactory
      .getLogger(LinesWriter.class);

    private List<Line> lines;
    private FileUtils fu;

    @Override
    public void beforeStep(StepExecution stepExecution) {
        ExecutionContext executionContext = stepExecution
          .getJobExecution()
          .getExecutionContext();
        this.lines = (List<Line>) executionContext.get("lines");
        fu = new FileUtils("output.csv");
        logger.debug("Lines Writer initialized.");
    }

    @Override
    public RepeatStatus execute(StepContribution stepContribution, 
      ChunkContext chunkContext) throws Exception {
        for (Line line : lines) {
            fu.writeLine(line);
            logger.debug("Wrote line " + line.toString());
        }
        return RepeatStatus.FINISHED;
    }

    @Override
    public ExitStatus afterStep(StepExecution stepExecution) {
        fu.closeWriter();
        logger.debug("Lines Writer ended.");
        return ExitStatus.COMPLETED;
    }
}

우리는 작업 구현을 마쳤습니다! 테스트를 실행하고 결과를 봅시다.

4.7. Tasklet방식 실행 하기

작업을 실행하기 위해 테스트를 작성합니다.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TaskletsConfig.class)
public class TaskletsTest {

    @Autowired
    private JobLauncherTestUtils jobLauncherTestUtils;

    @Test
    public void givenTaskletsJob_whenJobEnds_thenStatusCompleted()
      throws Exception {

        JobExecution jobExecution = jobLauncherTestUtils.launchJob();
        assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus());
    }
}

ContextConfiguration 주석은 작업 정의가있는 Spring 컨텍스트 구성 클래스를 가리키고 있습니다.

테스트를 실행하기 전에 두 개의 추가 Bean을 추가해야합니다.

@Bean
public JobLauncherTestUtils jobLauncherTestUtils() {
    return new JobLauncherTestUtils();
}

@Bean
public JobRepository jobRepository() throws Exception {
    MapJobRepositoryFactoryBean factory
      = new MapJobRepositoryFactoryBean();
    factory.setTransactionManager(transactionManager());
    return (JobRepository) factory.getObject();
}

@Bean
public PlatformTransactionManager transactionManager() {
    return new ResourcelessTransactionManager();
}

@Bean
public JobLauncher jobLauncher() throws Exception {
    SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
    jobLauncher.setJobRepository(jobRepository());
    return jobLauncher;
}

다 준비 됐어! 계속해서 테스트를 실행하십시오!

작업이 완료되면 output.csv 에 예상 내용이 있으며 로그에 실행 흐름이 표시됩니다.

[main] DEBUG o.b.t.tasklets.LinesReader - Lines Reader initialized.
[main] DEBUG o.b.t.tasklets.LinesReader - Read line: [Mae Hodges,10/22/1972]
[main] DEBUG o.b.t.tasklets.LinesReader - Read line: [Gary Potter,02/22/1953]
[main] DEBUG o.b.t.tasklets.LinesReader - Read line: [Betty Wise,02/17/1968]
[main] DEBUG o.b.t.tasklets.LinesReader - Read line: [Wayne Rose,04/06/1977]
[main] DEBUG o.b.t.tasklets.LinesReader - Read line: [Adam Caldwell,09/27/1995]
[main] DEBUG o.b.t.tasklets.LinesReader - Read line: [Lucille Phillips,05/14/1992]
[main] DEBUG o.b.t.tasklets.LinesReader - Lines Reader ended.
[main] DEBUG o.b.t.tasklets.LinesProcessor - Lines Processor initialized.
[main] DEBUG o.b.t.tasklets.LinesProcessor - Calculated age 45 for line [Mae Hodges,10/22/1972]
[main] DEBUG o.b.t.tasklets.LinesProcessor - Calculated age 64 for line [Gary Potter,02/22/1953]
[main] DEBUG o.b.t.tasklets.LinesProcessor - Calculated age 49 for line [Betty Wise,02/17/1968]
[main] DEBUG o.b.t.tasklets.LinesProcessor - Calculated age 40 for line [Wayne Rose,04/06/1977]
[main] DEBUG o.b.t.tasklets.LinesProcessor - Calculated age 22 for line [Adam Caldwell,09/27/1995]
[main] DEBUG o.b.t.tasklets.LinesProcessor - Calculated age 25 for line [Lucille Phillips,05/14/1992]
[main] DEBUG o.b.t.tasklets.LinesProcessor - Lines Processor ended.
[main] DEBUG o.b.t.tasklets.LinesWriter - Lines Writer initialized.
[main] DEBUG o.b.t.tasklets.LinesWriter - Wrote line [Mae Hodges,10/22/1972,45]
[main] DEBUG o.b.t.tasklets.LinesWriter - Wrote line [Gary Potter,02/22/1953,64]
[main] DEBUG o.b.t.tasklets.LinesWriter - Wrote line [Betty Wise,02/17/1968,49]
[main] DEBUG o.b.t.tasklets.LinesWriter - Wrote line [Wayne Rose,04/06/1977,40]
[main] DEBUG o.b.t.tasklets.LinesWriter - Wrote line [Adam Caldwell,09/27/1995,22]
[main] DEBUG o.b.t.tasklets.LinesWriter - Wrote line [Lucille Phillips,05/14/1992,25]
[main] DEBUG o.b.t.tasklets.LinesWriter - Lines Writer ended.

그것은 Tasklet을위한 것입니다. 이제 Chunks 접근법으로 넘어갈 수 있습니다.

5 . 청크 방식

5.1. 소개 및 디자인

이름에서 알 수 있듯이이 방법 은 데이터 청크에 대해 작업을 수행합니다 . 즉, 한 번에 모든 행을 읽고 처리하고 쓰는 대신 한 번에 고정 된 양의 레코드 (청크)를 읽고 처리하고 씁니다.

그런 다음 파일에 더 이상 데이터가 없을 때까지주기를 반복합니다.

결과적으로 흐름이 약간 다릅니다.

  1. 선이있는 동안 :
    • X 줄의 행에 대해 :
      • 한 줄을 읽으십시오
      • 한 줄 처리
    • X 라인을 씁니다.

따라서 청크 지향 접근 방식 을 위해 3 개의 빈 을 생성해야합니다 .

public class LineReader {
     // ...
}

public class LineProcessor {
    // ...
}

public class LinesWriter {
    // ...
}

구현으로 이동하기 전에 작업을 구성 해 봅시다.

5.2. 구성

작업 정의도 다르게 보입니다 :

@Configuration
@EnableBatchProcessing
public class ChunksConfig {

    @Autowired
    private JobBuilderFactory jobs;

    @Autowired
    private StepBuilderFactory steps;

    @Bean
    public ItemReader<Line> itemReader() {
        return new LineReader();
    }

    @Bean
    public ItemProcessor<Line, Line> itemProcessor() {
        return new LineProcessor();
    }

    @Bean
    public ItemWriter<Line> itemWriter() {
        return new LinesWriter();
    }

    @Bean
    protected Step processLines(ItemReader<Line> reader,
      ItemProcessor<Line, Line> processor, ItemWriter<Line> writer) {
        return steps.get("processLines").<Line, Line> chunk(2)
          .reader(reader)
          .processor(processor)
          .writer(writer)
          .build();
    }

    @Bean
    public Job job() {
        return jobs
          .get("chunksJob")
          .start(processLines(itemReader(), itemProcessor(), itemWriter()))
          .build();
    }

}

이 경우 하나의 작업 만 수행하는 단계는 하나뿐입니다.

그러나이 태스크 릿 은 데이터 청크에 대해 작동하는 리더, 라이터 및 프로세서를 정의합니다 .

(가)주의 간격 커밋 데이터의 양이 하나 개의 덩어리로 처리 될 나타낸다 . 우리의 일은 한 번에 두 줄씩 읽고 처리하고 쓸 것입니다.

이제 청크 로직을 추가 할 준비가되었습니다!

5.3. 청크 LineReader 구성

LineReader 는 하나의 레코드를 읽고 그 내용으로 Line 인스턴스를 리턴합니다 .

독자가 되려면 클래스에서 ItemReader 인터페이스 를 구현해야합니다 .

public class LineReader implements ItemReader<Line> {
     @Override
     public Line read() throws Exception {
         Line line = fu.readLine();
         if (line != null) 
           logger.debug("Read line: " + line.toString());
         return line;
     }
}

코드는 간단하며 한 줄만 읽고 반환합니다. 또한 이 클래스의 최종 버전에 대해 StepExecutionListener 를 구현합니다 .

public class LineReader implements
  ItemReader<Line>, StepExecutionListener {

    private final Logger logger = LoggerFactory
      .getLogger(LineReader.class);

    private FileUtils fu;

    @Override
    public void beforeStep(StepExecution stepExecution) {
        fu = new FileUtils("taskletsvschunks/input/tasklets-vs-chunks.csv");
        logger.debug("Line Reader initialized.");
    }

    @Override
    public Line read() throws Exception {
        Line line = fu.readLine();
        if (line != null) logger.debug("Read line: " + line.toString());
        return line;
    }

    @Override
    public ExitStatus afterStep(StepExecution stepExecution) {
        fu.closeReader();
        logger.debug("Line Reader ended.");
        return ExitStatus.COMPLETED;
    }
}

것으로 나타났습니다해야 beforeStep애프터이 전에 각각 전체 단계 이후에 실행합니다.

5.4. 청크 LineProcessor 구성

LineProcessorLineReader 와 거의 동일한 논리를 따릅니다 .

그러나이 경우 ItemProcessor 및 해당 메소드 process ()를 구현합니다 .

public class LineProcessor implements ItemProcessor<Line, Line> {

    private Logger logger = LoggerFactory.getLogger(LineProcessor.class);

    @Override
    public Line process(Line line) throws Exception {
        long age = ChronoUnit.YEARS
          .between(line.getDob(), LocalDate.now());
        logger.debug("Calculated age " + age + " for line " + line.toString());
        line.setAge(age);
        return line;
    }

}

프로세스 () 메소드는, 입력 라인을 얻어이를 처리 및 출력 라인을 반환한다 . 다시 StepExecutionListener 도 구현 합니다.

public class LineProcessor implements
  ItemProcessor<Line, Line>, StepExecutionListener {

    private Logger logger = LoggerFactory.getLogger(LineProcessor.class);

    @Override
    public void beforeStep(StepExecution stepExecution) {
        logger.debug("Line Processor initialized.");
    }

    @Override
    public Line process(Line line) throws Exception {
        long age = ChronoUnit.YEARS
          .between(line.getDob(), LocalDate.now());
        logger.debug(
          "Calculated age " + age + " for line " + line.toString());
        line.setAge(age);
        return line;
    }

    @Override
    public ExitStatus afterStep(StepExecution stepExecution) {
        logger.debug("Line Processor ended.");
        return ExitStatus.COMPLETED;
    }
}

5.5. 청크 LinesWriter 구성

리더 및 프로세서와 달리 LinesWriter 는 전체 행 청크를 작성하여 행 목록 을 수신합니다 .

public class LinesWriter implements
  ItemWriter<Line>, StepExecutionListener {

    private final Logger logger = LoggerFactory
      .getLogger(LinesWriter.class);

    private FileUtils fu;

    @Override
    public void beforeStep(StepExecution stepExecution) {
        fu = new FileUtils("output.csv");
        logger.debug("Line Writer initialized.");
    }

    @Override
    public void write(List<? extends Line> lines) throws Exception {
        for (Line line : lines) {
            fu.writeLine(line);
            logger.debug("Wrote line " + line.toString());
        }
    }

    @Override
    public ExitStatus afterStep(StepExecution stepExecution) {
        fu.closeWriter();
        logger.debug("Line Writer ended.");
        return ExitStatus.COMPLETED;
    }
}

LinesWriter 코드는 스스로를 말합니다. 그리고 다시, 우리는 우리의 직업을 시험 할 준비가되었습니다.

5.6. 청크방식 잡 실행

우리는 태스크 릿 접근 방식을 위해 만든 것과 동일한 새로운 테스트를 만들 것입니다.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ChunksConfig.class)
public class ChunksTest {

    @Autowired
    private JobLauncherTestUtils jobLauncherTestUtils;

    @Test
    public void givenChunksJob_whenJobEnds_thenStatusCompleted() 
      throws Exception {

        JobExecution jobExecution = jobLauncherTestUtils.launchJob();

        assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus()); 
    }
}

구성한 후 ChunksConfig을 위해 위의 설명에 따라 TaskletsConfig , 우리는 테스트를 실행하기위한 모든 준비!

작업이 완료되면 output.csv 에 예상 결과가 다시 포함되고 로그에 흐름이 설명되어 있음을 알 수 있습니다 .

[main] DEBUG o.b.t.chunks.LineReader - Line Reader initialized.
[main] DEBUG o.b.t.chunks.LinesWriter - Line Writer initialized.
[main] DEBUG o.b.t.chunks.LineProcessor - Line Processor initialized.
[main] DEBUG o.b.t.chunks.LineReader - Read line: [Mae Hodges,10/22/1972]
[main] DEBUG o.b.t.chunks.LineReader - Read line: [Gary Potter,02/22/1953]
[main] DEBUG o.b.t.chunks.LineProcessor - Calculated age 45 for line [Mae Hodges,10/22/1972]
[main] DEBUG o.b.t.chunks.LineProcessor - Calculated age 64 for line [Gary Potter,02/22/1953]
[main] DEBUG o.b.t.chunks.LinesWriter - Wrote line [Mae Hodges,10/22/1972,45]
[main] DEBUG o.b.t.chunks.LinesWriter - Wrote line [Gary Potter,02/22/1953,64]
[main] DEBUG o.b.t.chunks.LineReader - Read line: [Betty Wise,02/17/1968]
[main] DEBUG o.b.t.chunks.LineReader - Read line: [Wayne Rose,04/06/1977]
[main] DEBUG o.b.t.chunks.LineProcessor - Calculated age 49 for line [Betty Wise,02/17/1968]
[main] DEBUG o.b.t.chunks.LineProcessor - Calculated age 40 for line [Wayne Rose,04/06/1977]
[main] DEBUG o.b.t.chunks.LinesWriter - Wrote line [Betty Wise,02/17/1968,49]
[main] DEBUG o.b.t.chunks.LinesWriter - Wrote line [Wayne Rose,04/06/1977,40]
[main] DEBUG o.b.t.chunks.LineReader - Read line: [Adam Caldwell,09/27/1995]
[main] DEBUG o.b.t.chunks.LineReader - Read line: [Lucille Phillips,05/14/1992]
[main] DEBUG o.b.t.chunks.LineProcessor - Calculated age 22 for line [Adam Caldwell,09/27/1995]
[main] DEBUG o.b.t.chunks.LineProcessor - Calculated age 25 for line [Lucille Phillips,05/14/1992]
[main] DEBUG o.b.t.chunks.LinesWriter - Wrote line [Adam Caldwell,09/27/1995,22]
[main] DEBUG o.b.t.chunks.LinesWriter - Wrote line [Lucille Phillips,05/14/1992,25]
[main] DEBUG o.b.t.chunks.LineProcessor - Line Processor ended.
[main] DEBUG o.b.t.chunks.LinesWriter - Line Writer ended.
[main] DEBUG o.b.t.chunks.LineReader - Line Reader ended.

우리는 같은 결과와 다른 흐름을 가지고 있습니다. 로그는이 접근 방식에 따라 작업이 어떻게 실행되는지를 분명하게 보여줍니다.

6. 결론

상황에 따라 다른 접근 방식이 필요하다는 것을 알 수 있습니다. Tasklet은 '다른 작업 후 하나의 작업'시나리오에 대해 더 자연 스럽지만 청크는 페이지에 읽은 읽기 또는 메모리에 많은 양의 데이터를 유지하고 싶지 않은 상황을 처리 할 수있는 간단한 솔루션을 제공합니다.

이 예제의 완전한 구현은 GitHub 프로젝트 에서 찾을 수 있습니다 .

참고

https://www.baeldung.com/spring-batch-tasklet-chunk

반응형

'Spring' 카테고리의 다른 글

Spring batch 로 CSV(액셀) 만들기  (0) 2020.06.27
Spring batch 재시도  (0) 2020.06.25
Spring Boot 란  (0) 2020.06.22
Spring boot web filter 예제  (0) 2020.06.21
Spring, Spring boot mybatis 예제  (0) 2020.06.21