Spring Batch는 대용량 레코드에 최적화 및 파티셔닝 기술로 고성능 작업을 가능하게 하는 기능을 제공한다.
Spring Batch에서 Batch가 실패하면 처음부터가 아닌 실패한 지점부터 실행한다.
또한, 중복 실행을 막기 위해 성공한 이력이 있는 Batch는 동일한 Parameters로 실행하는 것을 방지한다.
Job
JobInstance
JobParameters
JobExecution
Step
StepExecution
ExecutionContext
JobRepository
JobLauncher
ItemReader
ItemWriter
https://velog.io/@gillog/Batch-Application-생성하기
dependencies {
...
// Batch
implementation 'org.springframework.boot:spring-boot-starter-batch'
...
}
@Slf4j
@Configuration
@EnableBatchProcessing
@RequiredArgsConstructor
public class BatchConfig {}
@EnableBatchProcessing
추가@Slf4j
@Configuration
@EnableBatchProcessing
@RequiredArgsConstructor
public class BatchConfig {
private final JobBuilderFactory jobBuilderFactory;
private final StepBuilderFactory stepBuilderFactory;
private final ProblemRepository problemRepository;
@Bean
public Job removeDeletedProblemJob() {
Job job = jobBuilderFactory.get("job") **// (1)**
.start(removeDeletedProblemStep()) **// (2)**
.build();
return job;
}
@Bean
public Step removeDeletedProblemStep() {
return stepBuilderFactory.get("step")
.tasklet((contribution, chunkContext) -> { **// (3)**
log.info("[문제 완전 삭제] step start");
long deletedCount = problemRepository.deleteSoftDeletedProblem(); **// (4)**
log.info("[문제 완전 삭제] 삭제된 문제 : {} 문제", deletedCount);
return RepeatStatus.FINISHED;
})
.build();
}
}
(1) : JobBuilderFactory를 사용하여 Job을 정의
(2) : Job이 시작되면 removeDeletedProblemStep()
메서드를 실행
(3) : tasklet은 Step의 작업을 정의
(4) : soft delete된 문제를 완전히 삭제한 다음 몇 문제를 삭제했는지 로그로 출력
@Component
@RequiredArgsConstructor
public class BatchScheduler {
private final JobLauncher jobLauncher;
private final Job problemDeleteJob;
@Scheduled(cron = "0 0 0 * * ?") // 자정에 실행
void deleteProblemJob() throws JobExecutionAlreadyRunningException, JobRestartException,
JobInstanceAlreadyCompleteException, JobParametersInvalidException {
JobParameters jobParameters = new JobParametersBuilder()
.addLong("time", System.currentTimeMillis())
.toJobParameters();
jobLauncher.run(problemDeleteJob, jobParameters);
}
}
Job
은 재실행할 수 있지만, 동일한 JobParameters
로는 한 번만 실행할 수 있다.batch: // (1)
job:
enabled: false
jdbc: // (2)
initialize-schema: always
(1) : Spring Boot 실행 시점에 배치 작업이 실행되는 것을 방지
(2) : Spring Boot 실행할 때마다 Spring Batch 관련 테이블을 재생성
문제
2023-08-31 00:10:56.751 ERROR 56904 --- [ main] o.h.engine.jdbc.spi.SqlExceptionHelper : Cannot delete or update a parent row: a foreign key constraint fails (`psq`.`bookmark`, CONSTRAINT `FK2p0jv1kw42c9x87wsi1tb2gbf` FOREIGN KEY (`problem_id`) REFERENCES `problem` (`id`))
2023-08-31 00:10:56.762 ERROR 56904 --- [ main] o.s.batch.core.step.AbstractStep : Encountered an error executing step step in job job
org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
...
Caused by: java.sql.SQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`psq`.`bookmark`, CONSTRAINT `FK2p0jv1kw42c9x87wsi1tb2gbf` FOREIGN KEY (`problem_id`) REFERENCES `problem` (`id`))
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:117) ~[mysql-connector-j-8.0.32.jar:8.0.32]
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) ~[mysql-connector-j-8.0.32.jar:8.0.32]
at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:916) ~[mysql-connector-j-8.0.32.jar:8.0.32]
...
원인
해결
@Entity
@NoArgsConstructor
@Getter
public class Bookmark extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "member_id")
private Member member;
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "problem_id")
@OnDelete(action = OnDeleteAction.CASCADE) **// 추가**
private Problem problem;
public Bookmark(Member member, Problem problem) {
this.member = member;
this.problem = problem;
}
}
@OnDelete(action = OnDeleteAction.CASCADE)
코드를 추가해서 problem 엔티티가 삭제되면 bookmark도 삭제되도록 설정한다.https://khj93.tistory.com/entry/Spring-Batch란-이해하고-사용하기
https://velog.io/@gillog/Batch-Application-생성하기
https://gimmesome.tistory.com/204
https://hyunjun.kr/16