
진행할 순서는 다음과 같다.
1. csv 파일 저장할 엔티티 & 테이블 생성
2. csv 파일 읽어 매핑할 dto 생성
3. spring batch Job, step 생성
4. csv reader, writer 로직
5. 실행
dependencies {
// 추가
'org.springframework.boot:spring-boot-starter-batch'
}
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableBatchProcessing ///SimpleBatchConfiguration을 스프링 빈으로 등록
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@Builder
@Getter
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
@ToString
public class Schedule {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String month; //월
private String date; //날짜
private String event; //이벤트
}
테이블 생성

Repository 생성
package com.app.univchat.repository.school;
import com.app.univchat.domain.school.Schedule;
import org.springframework.data.jpa.repository.JpaRepository;
public interface ScheduleRepository extends JpaRepository<Schedule, Long> {
}
toEntity() 메서드 생성@Builder
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(value = "학시일정")
public class ScheduleDto {
@ApiModelProperty(name = "월", example = "8월")
private String month;
@ApiModelProperty(name = "날짜", example = "8.1 ~ 25")
private String date;
@ApiModelProperty(name = "이벤트", example = "휴학원 제출기간 (성심)")
private String event;
/**
* Schedule 엔티티 반환
* @return
*/
public Schedule toEntity(){
return Schedule.builder()
.month(this.month)
.date(this.date)
.event(this.event)
.build();
}
}
FileReaderJobConfig 클래스 생성
@Configuration
@RequiredArgsConstructor
public class FileReaderJobConfig {
private final JobBuilderFactory jobBuilderFactory;
private final StepBuilderFactory stepBuilderFactory;
private static final int chunkSize = 1000; //데이터 처리할 row size
/**
* 학사일정 저장 Job
* Job은 여러 Step을 가질 수 있음
*/
@Bean
public Job csvScheduleJob(){
return jobBuilderFactory.get("csvScheduleJob")
.start(csvScheduleReaderStep())
.build();
}
/**
* csv 파일 읽고 DB에 쓰는 Step
*/
@Bean
public Step csvScheduleReaderStep(){
return stepBuilderFactory.get("csvScheduleReaderStep")
//<reader에 넘겨줄 타입, writer에 넙겨줄 타입>
.<ScheduleDto, ScheduleDto>chunk(chunkSize)
// .reader() csv 파일 읽고 넘겨줌
// .writer() 받은 데잍터 DB에 저장
// .allowStartIfComplete(true)
.build();
}
}
/**
* class.csv 파일 읽기
*/
@Configuration
@RequiredArgsConstructor
public class CsvReader {
/**
* 학사일정 파일 읽기
*/
@Bean
public FlatFileItemReader<ScheduleDto> csvScheduleReader(){
/* 파일읽기 */
FlatFileItemReader<ScheduleDto> flatFileItemReader = new FlatFileItemReader<>();
flatFileItemReader.setResource(new ClassPathResource("/csv/schedule.csv")); //읽을 파일 경로 지정
flatFileItemReader.setEncoding("UTF-8"); //인토딩 설정
/* defaultLineMapper: 읽으려는 데이터 LineMapper을 통해 Dto로 매핑 */
DefaultLineMapper<ScheduleDto> defaultLineMapper = new DefaultLineMapper<>();
/* delimitedLineTokenizer : csv 파일에서 구분자 지정하고 구분한 데이터 setNames를 통해 각 이름 설정 */
DelimitedLineTokenizer delimitedLineTokenizer = new DelimitedLineTokenizer(","); //csv 파일에서 구분자
delimitedLineTokenizer.setNames("month", "date", "event"); //행으로 읽은 데이터 매칭할 데이터 각 이름
defaultLineMapper.setLineTokenizer(delimitedLineTokenizer); //lineTokenizer 설정
/* beanWrapperFieldSetMapper: 매칭할 class 타입 지정 */
BeanWrapperFieldSetMapper<ScheduleDto> beanWrapperFieldSetMapper = new BeanWrapperFieldSetMapper<>();
beanWrapperFieldSetMapper.setTargetType(ScheduleDto.class);
defaultLineMapper.setFieldSetMapper(beanWrapperFieldSetMapper); //fieldSetMapper 지정
flatFileItemReader.setLineMapper(defaultLineMapper); //lineMapper 지정
return flatFileItemReader;
}
}
import org.springframework.batch.item.ItemWriter;
@Configuration
@RequiredArgsConstructor
public class CsvScheduleWriter implements ItemWriter<ScheduleDto> {
private final ScheduleRepository scheduleRepository;
@Override
public void write(List<? extends ScheduleDto> items) throws Exception {
List<Schedule> scheduleList = new ArrayList<>();
items.forEach(getScheduleDto -> {
Schedule schedule = getScheduleDto.toEntity();
scheduleList.add(schedule);
});
scheduleRepository.saveAll(scheduleList);
}
}
@Configuration
@RequiredArgsConstructor
public class FileReaderJobConfig {
private final JobBuilderFactory jobBuilderFactory;
private final StepBuilderFactory stepBuilderFactory;
private final CsvReader csvReader; //추가
private final CsvScheduleWriter csvScheduleWriter; //추가
@Bean
public Step csvScheduleReaderStep(){
return stepBuilderFactory.get("csvScheduleReaderStep")
.<ScheduleDto, ScheduleDto>chunk(chunkSize)
.reader(csvReader.csvScheduleReader()) //추가
.writer(csvScheduleWriter) //추가
// .allowStartIfComplete(true)
.build();
}
}

BATCH_JOB_EXECUTION: Job Instance 추가된 것 확인 (3번째)

BATCH_STEP_EXECUTION: Step 동작 성공적으로 끝낸 것을 볼 수 있음(COMPLETED)

csv 파일에 있는 데이터 DB에 무사 저장한 것 확인

application.yml에 다음 추가
spring:
batch:
jdbc:
initialize-schema: always
step 설정에 다음 추가
@Bean
public Step csvScheduleReaderStep(){
return stepBuilderFactory.get("csvScheduleReaderStep")
.<ScheduleDto, ScheduleDto>chunk(chunkSize)
.reader(csvReader.csvScheduleReader())
.writer(csvScheduleWriter)
.allowStartIfComplete(true) //추가
.build();
}