概要
Spring BatchではChankのItemReaderを任意に入れ替えることができます。
CSVの読み込み
Spring BootのCSVファイルを読み込むライブラリを用いてItemReaderを作成します。
ItemReader
読み込むCSVファイルのデータ構造を作成します。
nameとvalueというふたつのフィールドを持った簡単なデータ構造を定義します。
- SourceItemDto.java
package com.sios.ex.springbatch; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; public class SourceItemDto { @Setter @Getter private String name; @Setter @Getter private String value; public SourceItemDto() { } }
CSVファイルを読み込んでSourceItemDtoを生成するItemReaderを作成します。
- SpringBatchSamp2e1Configuration.javaより抜粋
@Bean @StepScope public FlatFileItemReader<SourceItemDto> sourceItemReader( @Value("#{jobParameters['filename']}") String filename) { FlatFileItemReader<SourceItemDto> reader = new FlatFileItemReader<SourceItemDto>(); reader.setResource(new FileSystemResource(filename)); reader.setLineMapper(new DefaultLineMapper<SourceItemDto>() {{ setLineTokenizer(new DelimitedLineTokenizer() {{ setNames(new String[] {"name", "value"}); }}); setFieldSetMapper(new BeanWrapperFieldSetMapper<SourceItemDto>() {{ setTargetType(SourceItemDto.class); }}); }}); return reader; }
「@Value(“#{jobParameters[‘filename’]}”) String filename」はJobに指定したパラメータを受け取ります。
この場合@StepScodeアノテーションを指定する必要があります。
ItemProcessor
読み込んだCSVをデータベースに出力するためにデータベースのテーブルにエンティティを定義します。
- TargetItemEntity.java
package com.sios.ex.springbatch; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; import lombok.Data; import lombok.Getter; @Data @Entity @Table(name = "target_item") public class TargetItemEntity { @Id @Column(name = "name", nullable = false) @Getter private String name; @Column(name = "value", nullable = false) @Getter private String value; public TargetItemEntity() { } public TargetItemEntity( String name, String value) { this.name = name; this.value = value; } }
ItemProcessorはCSVから読み込んだSourceItemDtoのオブジェクトを受け取りTargetItemEntityのオブジェクトを返します。
- TargetItemProcessor.java
package com.sios.ex.springbatch; import org.springframework.batch.item.ItemProcessor; public class TargetItemProcessor implements ItemProcessor<SourceItemDto, TargetItemEntity> { @Override public TargetItemEntity process(SourceItemDto item) throws Exception { return new TargetItemEntity(item.getName(), item.getValue()); } } [/cdoe] ### ItemWriter **ItemWriter**はデータベースの**target_item**テーブルに出力するシンプルなものになります。 [code] @Bean public ItemWriter<TargetItemEntity> targetItemWriter() { RepositoryItemWriter<TargetItemEntity> writer = new RepositoryItemWriter<>(); writer.setRepository(targetItemRepository); writer.setMethodName("save"); return writer; }
ItemReaderの作成
ItemReaderはItemReader<T>を継承して作成することができます。
上記の例で使用したCSVファイルを読み込むItemReaderを実装する場合は次の通りです。
- CsvSourceItemReader.java
package com.sios.ex.springbatch; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.Reader; import java.util.ArrayList; import org.springframework.batch.item.ItemReader; import org.springframework.batch.item.NonTransientResourceException; import org.springframework.batch.item.ParseException; import org.springframework.batch.item.UnexpectedInputException; public class CsvSourceItemReader implements ItemReader<SourceItemDto> { private String filename; private ArrayList<SourceItemDto> items = null; private int nextIndex; public CsvSourceItemReader(String filename) { this.filename = filename; } private void readCsvFile() { items = new ArrayList<SourceItemDto>(); try { BufferedReader reader = new BufferedReader(new FileReader(filename)); try { for (;;) { String line = reader.readLine(); if (line == null) break; String[] fields = line.split(",", 2); SourceItemDto item = new SourceItemDto(); item.setName(fields[0]); item.setValue(fields[1]); items.add(item); } } finally { reader.close(); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } @Override public SourceItemDto read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException { if (items == null) { readCsvFile(); nextIndex = 0; } SourceItemDto item = null; if (nextIndex < items.size()) { item = items.get(nextIndex); nextIndex++; } return item; } }
read()メソッドが呼び出されるたびにSourceItemDtoのオブジェクトを返します。
返すSourceItemDtoのオブジェクトが終了したらnullを返します。
StepのItemReaderの定義は次のようになります。
- SpringBatchSamp2e1Configuration.javaより抜粋
@Bean @StepScope public CsvSourceItemReader sourceItemReader( @Value("#{jobParameters['filename']}") String filename) { return new CsvSourceItemReader(filename); }
これらのように独自のItemReaderを作成することでさまざまな入力に対応したバッチ処理を実現することができます。