개념
배치 작업 중 정보를 저장하기 위한 저장소 역할입니다.
배치 작업 실행과 관련된 모든 메타데이터를 저장합니다. B. 작업이 실행될 때, 종료될 때 실행 횟수 및 실행 결과.
– CRUD 기능은 JobLauncher, Job 및 Step 구현 내에서 처리됩니다.

작업 저장소
| 작업 저장소 | |
| 부울 isJobInstanceExists(String jobName, JobParameters jobParameters) | JobInstance가 있는지 확인하십시오. |
| JobExecution createJobExecution(String JobName, JobParameter JobParameter) | 작업이 실행될 때마다 jobExecution 생성 |
| JobExecution getLastJobExecution(String JobName, JobParameter JobParameter) | 작업 실행 기록의 마지막 JobExecution을 반환합니다. |
| 무효 업데이트(JobExecution jobExecution) | 주문 실행 정보 업데이트 |
| 무효 업데이트(StepExecution stepExecution) | 단계 실행 정보 업데이트 |
| 무효 추가(StepExectuion stepExectuion) | 해당 실행 단계의 새로운 stepExectuion을 저장합니다. |
| 무효 updateExecutionContext(StepExecution stepExecution) | 단계의 공유 데이터 및 상태 정보가 포함된 실행 컨텍스트 업데이트 |
| 무효 updateExecutionContext(JobExecution jobExecution) | 작업의 공유 데이터 및 상태 정보가 포함된 실행 컨텍스트 업데이트 |
| StepExecution getLastStepExecution(JobInstance jobInstance, String stepName) | 해당 단계의 실행 히스토리에서 마지막 StepExecution을 반환합니다. |
JobRepository 설정
- @EnableBatchProcessing을 선언하면 JobRepository가 자동으로 bean으로 생성된다.
- BatchConfigurer 인터페이스를 구현하거나 BasicBatchConfigurer를 상속하여 JobRepository 설정을 사용자 지정할 수 있습니다.
1. JDBC 방식 설정
JobRepositoryFactoryBean
- 내부적으로 트랜잭션은 AOP 기술을 통해 처리됩니다.
- 트랜잭션 격리의 기본값은 SERIALIZEBLE이며 다른 수준(READ_COMMAND, REPEATABLE_READ)으로 설정할 수 있습니다.
- 메타 테이블의 테이블 접두사를 변경할 수 있습니다. 기본값은 “BATCH_”입니다.
소스 코드
@Override
protected JobRepository createJobRepository() throws Exception {
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setDataSource(dataSource);
factory.setTransactionManager(transactionManager);
factory.setIsolationLevelForCreate("ISOLATION_SERIALIZABLE"); // isolation 수준, 기본값은 “ISOLATION_SERIALIZABLE”
factory.setTablePrefix(“SYSTEM_"); // 테이블 Prefix, 기본값은 “BATCH_”, BATCH_JOB_EXECUTION 가 SYSTEM_JOB_EXECUTION 으로 변경됨
factory.setMaxVarCharLength(1000); // varchar 최대 길이(기본값 2500)
return factory.getObject(); // Proxy 객체가 생성됨 (트랜잭션 Advice 적용 등을 위해 AOP 기술 적용)
}
기억에
MapJobRepositoryFactoryBean
- 성능상의 이유로 도메인 개체를 DB에 저장하지 않으려는 경우
- 일반적으로 신속한 테스트 또는 프로토타이핑이 필요할 때 사용됩니다.
@Override
protected JobRepository createJobRepository() throws Exception {
MapJobRepositoryFactoryBean factory = new MapJobRepositoryFactoryBean();
factory.setTransactionManager(transactionManager); // ResourcelessTransactionManager 사용
return factory.getObject();
}
소스 코드
JobRepositoryConfiguration.java
package io.springbatch.springbatchlecture;
import lombok.RequiredArgsConstructor;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@RequiredArgsConstructor
@Configuration
public class JobRepositoryConfiguration {
private final JobBuilderFactory jobBuilderFactory;
private final StepBuilderFactory stepBuilderFactory;
private final JobRepositoryListener jobRepositoryListener;
@Bean
public Job BatchJob() {
return this.jobBuilderFactory.get("Job")
.start(step1())
.next(step2())
.listener(jobRepositoryListener)
.build();
}
@Bean
public Step step1() {
return stepBuilderFactory.get("step1")
.tasklet(new Tasklet() {
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
return RepeatStatus.FINISHED;
}
})
.build();
}
@Bean
public Step step2() {
return stepBuilderFactory.get("step2")
.tasklet((contribution, chunkContext) -> null)
.build();
}
}
CustomBatchConfigurer.java
package io.springbatch.springbatchlecture;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean;
import org.springframework.boot.autoconfigure.batch.BasicBatchConfigurer;
import org.springframework.boot.autoconfigure.batch.BatchProperties;
import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
@Configuration
public class CustomBatchConfigurer extends BasicBatchConfigurer {
private final DataSource dataSource;
protected CustomBatchConfigurer(BatchProperties properties, DataSource dataSource, TransactionManagerCustomizers transactionManagerCustomizers) {
super(properties, dataSource, transactionManagerCustomizers);
this.dataSource = dataSource;
}
@Override
protected JobRepository createJobRepository() throws Exception {
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setDataSource(dataSource);
factory.setTransactionManager(getTransactionManager());
factory.setIsolationLevelForCreate("ISOLATION_SERIALIZABLE"); // isolation 수준, 기본값은 “ISOLATION_SERIALIZABLE”
factory.setTablePrefix("BATCH_"); // 테이블 Prefix, 기본값은 “BATCH_”,
// BATCH_JOB_EXECUTION 가 SYSTEM_JOB_EXECUTION 으로 변경됨
// 실제 테이블명이 변경되는 것은 아니다
factory.setMaxVarCharLength(1000); // varchar 최대 길이(기본값 2500)
return factory.getObject(); // Proxy 객체가 생성됨 (트랜잭션 Advice 적용 등을 위해 AOP 기술 적용)
}
}
JobRepositoryListener
package io.springbatch.springbatchlecture;
import org.springframework.batch.core.*;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class JobRepositoryListener implements JobExecutionListener {
@Autowired
private JobRepository jobRepository;
@Override
public void beforeJob(JobExecution jobExecution) {
}
@Override
public void afterJob(JobExecution jobExecution) {
String jobName = jobExecution.getJobInstance().getJobName();
JobParameters jobParameters = new JobParametersBuilder().addString("requestDate", "20210102").toJobParameters();
JobExecution lastExecution = jobRepository.getLastJobExecution(jobName, jobParameters);
if(lastExecution != null) {
for (StepExecution execution : lastExecution.getStepExecutions()) {
BatchStatus status = execution.getStatus();
System.out.println("BatchStatus = " + status.isRunning());
System.out.println("BatchStatus = " + status.name());
}
}
}
}
실행 결과
메타데이터 테이블이 “BATCH_”로 구성되어 있기 때문에 오류가 지속됩니다.
![[Spring] 유효성 검증 [Spring] 유효성 검증](https://en.korea-industry.kr/wp-content/plugins/contextual-related-posts/default.png)
