Spring Batch その4
今回も前回から時間が経過していますが、Spring Batch の続きです。
今回は、やっとJob作成です。
作成するJobは、
- CSVファイルからデータを取得
- 取得したデータを編集
- データベースに登録
するJobです。
Spring Batchの場合、chunk(チャンク)という仕組みがあるので、この仕組みに沿って作成します。
ガワ作成
Jobを定義するクラスを作成します。
@EnableBatchProcessing @Import({ BatchContext.class }) public class Csv2dbJob01Config { }
@EnableBatchProcessingは、Spring Batchの設定クラスに必要なアノテーションです。
本来は@Configurationも必要なのですが、BatchContextをImportしていることで、無くても大丈夫なようです。
BatchContextは前回作成したBatch用のApplicationContextです。
このBatchContextをImportすることで、DataSource設定とMyBatis設定を取り込みます。
CSVファイル読み込み処理
- 東京都住所情報
- 先頭行に項目名がある
- Shift_JISのファイル
です。
CSVファイル読み込みは、Spring Batchが提供しているファイルを簡単に扱えるクラスを利用します。
/** CSVファイルパス */ private static final String CSV_FILE_PATH = "D:/CsvData/13tokyo.csv"; @Bean public FlatFileItemReader<AddressDto> addressReader() { DelimitedLineTokenizer lineTokenizer = new DelimitedLineTokenizer(); lineTokenizer.setNames(new String[] { "id", "prefCd", "cityCd", "townCd", "zip", "officeFlg", "deleteFlg", "prefName", "prefKana", "cityName", "cityKana", "townName", "townKana", "townMemo", "kyotoStreet", "azaName", "azaKana", "memo", "officeName", "officeKana", "officeAddress", "newId" }); BeanWrapperFieldSetMapper<AddressDto> fieldSetMapper = new BeanWrapperFieldSetMapper<>(); fieldSetMapper.setTargetType(AddressDto.class); DefaultLineMapper<AddressDto> lineMapper = new DefaultLineMapper<>(); lineMapper.setLineTokenizer(lineTokenizer); lineMapper.setFieldSetMapper(fieldSetMapper); FlatFileItemReader<AddressDto> reader = new FlatFileItemReader<>(); reader.setResource(new FileSystemResource(CSV_FILE_PATH)); reader.setLinesToSkip(1); reader.setEncoding("Shift_JIS"); reader.setLineMapper(lineMapper); return reader; }
このコードを実行すると、CSVファイルの1行がAddressDtoに設定されます。
コード内容は、
DelimitedLineTokenizerでは、行をカンマで区切り、各項目に名前を付けています。
(DelimitedLineTokenizerはデフォルトがカンマ区切りです)
BeanWrapperFieldSetMapperでは、AddressDtoのフィールド名にマッピングすることを定義しています。
これらをDefaultLineMapperで包んでFlatFileItemReaderに設定しています。
FlatFileItemReaderのsetLinesToSkipは、スキップする行数を指定しています。
今回使用するCSVは先頭行に項目名がある為、1行スキップする必要があります。
取得データの編集処理
以下のルールで取得データを編集する
- 市区町村名が東村山市以外は無視
- 郵便番号のハイフンを削除
データ編集処理では、Spring Batchが提供しているItemProcessorを実装したクラスを作成します。
package jp.tokyo.higashimurayama.tohnaman.batch.jobs.csv2db; public class CsvToModelItemProcessor implements ItemProcessor<AddressDto, MstAddress> { @Override public MstAddress process(AddressDto item) throws Exception { String cityName = item.getCityName(); if (cityName.equals("東村山市")) { MstAddress output = new MstAddress(); BeanUtils.copyProperties(item, output); output.setZip(item.getZip().replace("-", "")); return output; } return null; } }
引数はItemReaderから渡されるAddressDtoで、戻り値はItemWriterに渡すMstAddressです。
@Bean public CsvToModelItemProcessor csvToModelItemProcessor() { return new CsvToModelItemProcessor(); }
作成したCsvToModelItemProcessorをCsv2dbJob01ConfigにBeanとして設定ファイルに追加する
データベース登録
データベース登録には、MyBatisが提供しているMyBatisBatchItemWriterを作成します。
Spring BatchでもIbatisBatchItemWriterを提供していますが、Deprecatedなので使用しません。
@Autowired private SqlSessionFactory sqlSessionFactory; @Bean public MyBatisBatchItemWriter<MstAddress> addressWriter() { MyBatisBatchItemWriter<MstAddress> writer = new MyBatisBatchItemWriter<>(); writer.setStatementId("jp.tokyo.higashimurayama.tohnaman.batch.mybatis.mapper.MstAddressMapper.insert"); writer.setSqlSessionFactory(sqlSessionFactory); return writer; }
setStatementIdで指定しているIDは、MyBatis Generatorを使用して自動生成したmapperのIDです。
これで、CsvToModelItemProcessor から渡されたMstAddress の内容をMST_ADDRESSにinsertします。