Spring boot의 batch를 이용해 일괄작업을 진행하려 한다.
준비할 것들: .csv파일, build.gragle에 의존성 주입, Entity 코드 작성, Repository 코드 작성, application에 어노테이션 추가
build.gradle에 의존성 주입하기
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-batch'
}
Entity 생성
@Getter
@Setter
@NoArgsConstructor
@Entity
public class Tag {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long tagId;
private String tagName;
private String tagDescription;
}
Repository 생성
public interface TagRepository extends JpaRepository<Tag, Long> {
}
Application에 어노테이션 추가
@EnableBatchProcessing <--------------
@SpringBootApplication
public class PreProjectApplication {
public static void main(String[] args) {
SpringApplication.run(PreProjectApplication.class, args);
}
}
@EnableBatchProcessing 어노테이션을 추가해준다.
이제 FileItemReaderJobConfig, CsvWriter, CsvReader 세 가지를 구현해 주면 된다.
FileItemReaderJobConfig
@Slf4j
@Configuration
@RequiredArgsConstructor
public class FileItemReaderJobConfig {
private final JobBuilderFactory jobBuilderFactory;
private final StepBuilderFactory stepBuilderFactory;
private final CsvReader csvReader;
private final CsvWriter csvWriter;
private static final int chunkSize = 300;
@Bean
public Job csvFileItemReaderJob() {
return jobBuilderFactory.get("csvFileItemReaderJob")
.start(csvFileItemReaderStep())
.build();
}
@Bean
public Step csvFileItemReaderStep() {
return stepBuilderFactory.get("csvFileItemReaderStep")
.<Tag, Tag>chunk(chunkSize)
.reader(csvReader.csvFileItemReader())
.writer(csvWriter)
.build();
}
}
chunkSize는 한번에 입력되는 내용?
트랜젝션 단위라고 생각했다.
CsvReader
@Configuration
@RequiredArgsConstructor
public class CsvReader {
@Bean
public FlatFileItemReader<Tag> csvFileItemReader() {
FlatFileItemReader<Tag> flatFileItemReader = new FlatFileItemReader<>();
flatFileItemReader.setResource(new ClassPathResource("/csv/tag.csv"));
flatFileItemReader.setLinesToSkip(1);
flatFileItemReader.setEncoding("UTF-8");
DefaultLineMapper<Tag> defaultLineMapper = new DefaultLineMapper<>();
DelimitedLineTokenizer delimitedLineTokenizer = new DelimitedLineTokenizer(",");
delimitedLineTokenizer.setNames("id", "tagName", "tagDescription");
defaultLineMapper.setLineTokenizer(delimitedLineTokenizer);
BeanWrapperFieldSetMapper<Tag> beanWrapperFieldSetMapper = new BeanWrapperFieldSetMapper<>();
beanWrapperFieldSetMapper.setTargetType(Tag.class);
defaultLineMapper.setFieldSetMapper(beanWrapperFieldSetMapper);
flatFileItemReader.setLineMapper(defaultLineMapper);
return flatFileItemReader;
}
}
flatFileItemReader.setResource(new ClassPathResource("csv파일의 경로"));
csv 파일의 경로는 프로젝트 파일 내부 resources 디렉토리부터 적어주면 된다.
delimitedLineTokenizer.setNames("엔티티 내부 컬럼");
엔티티에 포함된 변수에 맞게 이름을 적어주면 된다.
DelimitedLineTokenizer delimitedLineTokenizer = new DelimitedLineTokenizer(",");
에는 .csv파일 내부의 구분자 정보를 적어주면 된다.
CsvWriter
@Configuration
@RequiredArgsConstructor
public class CsvWriter implements ItemWriter<Tag> {
private final TagRepository tagRepository;
@Override
public void write(List<? extends Tag> list) throws Exception {
tagRepository.saveAll(new ArrayList<Tag>(list));
}
}
코드를 작성 한 후 어플리케이션을 실행하면
2023-04-16 11:08:47.684 INFO 14524 --- [ main] o.s.batch.core.step.AbstractStep : Step: [csvFileItemReaderStep] executed in 1s36ms
2023-04-16 11:08:47.689 INFO 14524 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [SimpleJob: [name=csvFileItemReaderJob]] completed with the following parameters: [{}] and the following status: [COMPLETED] in 1s49ms
위와 같은 로그를 확인할 수 있고,
데이터 베이스에도 잘 저장된 것을 확인할 수 있다.
'복습 > 개발 일지' 카테고리의 다른 글
헤더에 Authorization 추가 (0) | 2023.04.23 |
---|---|
Path parameters with the following names were not found in the request (0) | 2023.04.07 |
Location Header만 반환하는 메서드에 body 얹기 (0) | 2023.04.07 |
"Unauthorized" (0) | 2023.03.22 |
하나의 메서드에 두 개의@RequestBody 넣기 (0) | 2023.03.05 |