Spring Batch는 대용량 데이터를 효율적으로 처리하기 위한 프레임워크이다.
Chunk란 여러 개의 아이템을 묶은 하나의 덩어리, 블록을 의미한다.
한 번에 모든 행을 읽고 처리하고 쓰는 것이 아니라, 한 번에 고정 된 양의 레코드를 읽고 처리하는 방식이다.
청크 방식은 크게 세 가지 구성 요소로 이루어져 있다.
Product 데이터를 기반으로 Log를 생성하는 배치 작업을 실행하는 코드 실습을 해보자
@Bean
public Job makeProductLogJob(JobRepository jobRepository, Step makeProductLogStep1) {
return new JobBuilder("makeProductLogJob", jobRepository)
.start(makeProductLogStep1)
.incrementer(new RunIdIncrementer())
.build();
}
JobBuilder
를 사용해서 'makeProductLogJob'이라는 이름의 Job을 빌드한다..start()
: 해당 Job의 첫 번째 Step을 설정한다. @JobScope
@Bean
public Step makeProductLogStep1(
JobRepository jobRepository,
ItemReader<Product> step1Reader,
ItemProcessor<Product, ProductLog> step1Processor,
ItemWriter<ProductLog> step1Writer,
PlatformTransactionManager platformTransactionManager
) {
return new StepBuilder("makeProductLogStep1Tasklet", jobRepository)
.<Product, ProductLog>chunk(CHUNK_SIZE, platformTransactionManager)
.reader(step1Reader)
.processor(step1Processor)
.writer(step1Writer)
.build();
}
@JobScope
: Job 내에서 관리됨을 의미한다. <Product, ProductLog>
: ItemReader, ItemProcessor, ItemWriter의 입력 및 출력 유형을 나타낸다..chunk()
: 청크 방식으로 배치를 처리한다.CHUNK_SIZE
: 사이즈 만큼의 데이터를 한 번에 처리한다. @StepScope
@Bean
public ItemReader<Product> step1Reader() {
return new RepositoryItemReaderBuilder<Product>()
.name("step1Reader")
.repository(productRepository)
.methodName("findAll")
.pageSize(CHUNK_SIZE)
.sorts(Collections.singletonMap("id", Sort.Direction.ASC))
.build();
}
.name()
: ItemReader의 이름을 .repository()
: 사용할 Spring Data Repository를 설정한다..methodName()
: 리포지터리에서 사용할 메서드를 설정한다. 모든 데이터를 가져오기 위해 findAll을 썼다..pageSize()
: 한 번에 가져올 데이터의 수.sorts()
: 데이터를 읽어올 때 정렬 기준을 설정한다.@StepScope
@Bean
public ItemProcessor<Product, ProductLog> step1Processor() {
return product -> ProductLog
.builder()
.product(product)
.name(product.getName())
.build();
}
@StepScope
: Step 내에서 빈이 생성되고 관리된다. 즉, Step 실행 시에만 빈이 생성되고 Step이 끝나면 빈이 소멸된다.@StepScope
@Bean
public ItemWriter<ProductLog> step1Writer() {
return items -> items.forEach(item -> {
productLogRepository.save(item);
});
}