모르지 않다는 것은 아는것과 다르다.

Spring Batch

ItemWriter

채마스 2022. 2. 27. 01:21

ItemWriter interface

  • ItemWriter는 마지막으로 배치 처리 대상 데이터를 어떻게 처리할 지 결정한다.
    • DB에 데이터를 저장하거나, API로 서버에 요청하거나, 파일에 데이터를 write하거나 최종적으로 할 작업을 진행한다.
  • Step에서 ItemWriter는 필수이다.



csvItemWriter

    private ItemWriter<Person> csvItemWriter() throws Exception {
        BeanWrapperFieldExtractor<Person> fieldExtractor = new BeanWrapperFieldExtractor<>();
        fieldExtractor.setNames(new String[] {"id", "name", "age", "address"});

        DelimitedLineAggregator<Person> lineAggregator = new DelimitedLineAggregator<>();
        lineAggregator.setDelimiter(",");
        lineAggregator.setFieldExtractor(fieldExtractor);

        FlatFileItemWriter<Person> itemWriter = new FlatFileItemWriterBuilder<Person>()
                .name("csvFileItemWriter")
                .encoding("UTF-8")
                .resource(new FileSystemResource("output/test-output.csv"))
                .lineAggregator(lineAggregator)
                .headerCallback(writer -> writer.write("id,이름,나이,거주지"))
                .footerCallback(writer -> writer.write("---------------\n"))
                .append(true)
                .build();

        itemWriter.afterPropertiesSet();

        return itemWriter;
    }
  • csv 파일에 작성할 데이터를 추출하기 위해서 fieldExtractor 객체가 필요하다.
  • fieldExtractor로 필드명을 설정해 준다.
  • 각 필드의 데이터를 하나의 라인에 작성하기 위해서 구분자가 필요하다 -> lineAggregator로 설정가능
  • FileSystemResource 클래스로 어떤 경로에 파일을 생성할지 지정해준다.
  • headerCallback를 통해서 헤더를 추가해준다.
  • footerCallback를 통해서 푸터를 추가해준다.
  • append를 안해주면 파일명이 같으면 덮어쓰기 된다.
  • 풋터 뒤에 개행문자를 추가해 주는게 좋다.



jdbcItemWriter

    @Bean
    public Step jdbcBatchItemWriterStep(){
        return stepBuilderFactory.get("jdbcBatchItemWriterStep")
                .<Person, Person>chunk(10)
                .reader(itemReader())
                .writer(jdbcBatchItemWriter())
                .build();
    }

    private ItemWriter<Person> jdbcBatchItemWriter() {
        JdbcBatchItemWriter<Person> itemWriter = new JdbcBatchItemWriterBuilder<Person>()
                .dataSource(dataSource)
                .itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
                .sql("insert into person(name, age, address) values(:name, :age, :address)")
                .build();
        itemWriter.afterPropertiesSet();
        return itemWriter;
    }
  • Person 객체를 파라미터로 자동으로 생성할 수 있는 BeanPropertyItemSqlParameterSourceProvider를 설정해준다.



jpaItemWriter

    @Bean
    public Step jpaItemWriterStep() throws Exception {
        return stepBuilderFactory.get("jpaItemWriterStep")
                .<Person, Person>chunk(10)
                .reader(itemReader())
                .writer(jpaItemWriter())
                .build();
    }

    private ItemWriter<Person> jpaItemWriter() throws Exception {
        JpaItemWriter<Person> itemWriter = new JpaItemWriterBuilder<Person>()
                .entityManagerFactory(entityManagerFactory)
                .usePersist(true)
                .build();

        itemWriter.afterPropertiesSet();;
        return itemWriter;
    }
  • select 쿼리가 매 요청마다 실행됨 -> jpaItemWriter는 별다른 설정 없이 실행할 경우 -> merge 메소드로 실행됨.
  • merge 메소드는 update하거나 insert 할 수 있는 메서드이다. -> 수정대상인지 확인하기 위해서 select 메서드가 실행되는 것이다. -> 그렇기 때문에 select 메서드로 인해 성능문제가 발생할 수 있다.
  • 위의 문제를 해결하기위해서 -> usePersist(true) 설정하면 select 메서드가 실행되지 않고 insert메서드만 실행되는 확인할 수 있다.



'Spring Batch' 카테고리의 다른 글

StepListener  (0) 2022.02.27
JobExecutionListener  (0) 2022.02.27
ItemProcessor  (0) 2022.02.27
ItemReader  (0) 2022.02.27
Tasklet, Chunk 비교  (0) 2022.02.27