본문 바로가기
개발/Spring

[Spring] 스프링 배치(Spring Batch) 가이드 따라가기 (6)

by devhooney 2022. 12. 20.
728x90

스프링 배치 가이드

 

- 지난 포스팅에서 튜토리얼 보고 따라해봤는데, 이번에는 개념부터 천천히 공부해보자.

- 책을 보고 공부하려 했으나, 스프링과 부트의 배치 사용 문법이 많이 달라 이동욱님의 블로그를 보고 공부했다.

https://devhooney.tistory.com/139

 

[Spring] 스프링 배치(Spring Batch) 가이드 따라가기 (2)

스프링 배치 가이드 - 지난 포스팅에서 튜토리얼 보고 따라해봤는데, 이번에는 개념부터 천천히 공부해보자. - 책을 보고 공부하려 했으나, 스프링과 부트의 배치 사용 문법이 많이 달라 이동욱

devhooney.tistory.com

 

 

1. ItemWriter

public interface ItemWriter<T> {

   /**
    * Process the supplied data element. Will not be called with any null items
    * in normal operation.
    *
    * @param items items to be written
    * @throws Exception if there are errors. The framework will catch the
    * exception and convert or rethrow it as appropriate.
    */
   void write(List<? extends T> items) throws Exception;

}

- ItemWriter 인터페이스는 Items List를 받는다.

배치 프로세스를 나타낸 그림

- ItemReader를 통해 각 항목을 개별적으로 읽고 이를 처리하기 위해 ItemProcessor로 전달

- 이 프로세스는 Chunk의 Item 개수 만큼 처리될 때 까지 계속 진행

- Chunk 단위만큼 처리가 완료되면 Writer에 전달되어 Writer에 명시되어 있는대로 일괄 처리

 

=> Reader와 Processor를 거쳐서 처리된 Item을 Chunk 단위만큼 쌓은 뒤 Writer에 전달!

 

 

2. Database Writer

- Writer는 Chunk단위의 마지막이므로 Flush 처리를 해줘야 한다.

- Writer가 받은 모든 Item이 처리된 후, Spring Batch는 현재 트랜잭션을 커밋한다.

- 데이터베이스와 관련된 Writer는 3가지

  • JdbcBatchItemWriter
  • HibernateItemWriter
  • JpaItemWriter

 

 

728x90

 

 

3. JdbcBatchItemWriter

- ORM을 사용하지 않는 경우 Writer는 대부분 JdbcBatchItemWriter를 사용

- JDBC의 Batch 기능을 사용하여 한번에 Query를 DB로 전달하며, DB 내부에서 쿼리들이 실행된다.

 

 

- 이유는 어플리케이션과 데이터베이스 간에 데이터를 주고 받는 횟수를 최소화하여 성능을 향상시키기 위한 것.

 

 

4. JpaItemWriter

- 예제 코드

@Slf4j
@RequiredArgsConstructor
@Configuration
public class JpaItemWriterJobConfiguration {
    private final JobBuilderFactory jobBuilderFactory;
    private final StepBuilderFactory stepBuilderFactory;
    private final EntityManagerFactory entityManagerFactory;

    private static final int chunkSize = 10;

    @Bean
    public Job jpaItemWriterJob() {
        return jobBuilderFactory.get("jpaItemWriterJob")
                .start(jpaItemWriterStep())
                .build();
    }

    @Bean
    public Step jpaItemWriterStep() {
        return stepBuilderFactory.get("jpaItemWriterStep")
                .<Pay, Pay2>chunk(chunkSize)
                .reader(jpaItemWriterReader())
                .processor(jpaItemProcessor())
                .writer(jpaItemWriter())
                .build();
    }

    @Bean
    public JpaPagingItemReader<Pay> jpaItemWriterReader() {
        return new JpaPagingItemReaderBuilder<Pay>()
                .name("jpaItemWriterReader")
                .entityManagerFactory(entityManagerFactory)
                .pageSize(chunkSize)
                .queryString("SELECT p FROM Pay p")
                .build();
    }

    @Bean
    public ItemProcessor<Pay, Pay2> jpaItemProcessor() {
        return pay -> new Pay2(pay.getAmount(), pay.getTxName(), pay.getTxDateTime());
    }

    @Bean
    public JpaItemWriter<Pay2> jpaItemWriter() {
        JpaItemWriter<Pay2> jpaItemWriter = new JpaItemWriter<>();
        jpaItemWriter.setEntityManagerFactory(entityManagerFactory);
        return jpaItemWriter;
    }


}

 

- ItemProcessor는 Pay에서 Pay2로 전달해주기 위한 것

- JpaItemWriter는 Pay라는 엔티티를 데이터베이스에 반영

- JpaItemWriter는 Entity 클래스를 제네릭으로 받아야 한다.

=> JpaItemWriter 는 넘어온 Item을 그대로 entityManger.merge()로 테이블에 반영을 하기 때문.

 

- 실행하면

 

 

- 데이터가 pay2에 write됐다.

 

 

 

 

 

728x90