Spring Batch その8
今回もSpring Batch です。
今回は、成功後の再実施で一意制約違反エラーで失敗する問題に対応します。
解決方法はいろいろありますが、作成しているバッチをマスタ更新バッチと位置付けて、
以下の仕様に変更します。
- 所定の場所にファイルが存在する場合にマスタ更新を実行する
- マスタ更新処理は、デリート&インサートで行う
では、早速行ってみよう!
マスタ更新ファイルの存在チェック
Tasklet作成
public class FileExistCheckTasklet implements Tasklet, InitializingBean { /** ファイルが存在しない場合のExitStatus */ public static final String NOT_EXIST = "NOT_EXIST"; /** ファイルパス */ private String filePath; @Override public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { if (!Files.exists(Paths.get(filePath))) { contribution.setExitStatus(new ExitStatus(NOT_EXIST)); } return RepeatStatus.FINISHED; } @Override public void afterPropertiesSet() throws Exception { Assert.notNull(filePath, "ファイルパスは必須です。"); } public void setFilePath(String filePath) { this.filePath = filePath; } }
汎用的に、ファイル存在チェックTaskletとして作成
マスタ更新ファイルの存在確認Step
@Bean public Step fileExistCheckStep() { // @formatter:off return stepBuilderFactory .get("fileExistCheckStep") .tasklet(fileExistCheckTasklet()) .build(); // @formatter:on } @Value("${csv2dbjob.filepath}") private String filePath; @Bean public FileExistCheckTasklet fileExistCheckTasklet() { FileExistCheckTasklet tasklet = new FileExistCheckTasklet(); tasklet.setFilePath(filePath); return tasklet; }
作成したTaskletを使用するStepを作成
Taskletの定義では、ファイルパスを設定ファイルから取得するようにしています
# csv2dbjob csv2dbjob.filepath=D:/work/MastarUpdate.txt
設定ファイルはこんなかんじ
マスタ更新処理の修正
マスタ削除Tasklet作成
public class MasterDeleteTasklet implements Tasklet { @Autowired private MstAddressMapper mstAddressMapper; @Override public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { this.mstAddressMapper.deleteByExample(null); return RepeatStatus.FINISHED; } }
WHERE句に何も設定しないDETETE文を実行するだけの単純なTasklet
マスタ削除Step
@Autowired private MasterDeleteTasklet masterDeleteTasklet; @Bean public Step masterDeleteStep() { // @formatter:off return stepBuilderFactory .get("masterDeleteStep") .tasklet(masterDeleteTasklet) .build(); // @formatter:on } @Bean public MasterDeleteTasklet masterDeleteTasklet() { return new MasterDeleteTasklet(); }
作成したマスタ削除Taskletを使用するStepを作成
ここでは定義したTaskletを DI しています。
理由は、MasterDeleteTasklet でmapperをDIしている為で、
定義したBeanをそのまま利用するとマスタ削除時に、
mapperがDIされず、ぬるぽが発生します。
Jobの修正
修正前
public Job csv2dbJob() { // @formatter:off return jobBuilderFactory .get("csv2dbJob") .listener(logListener) .flow(csv2dbStep()) .end() .build(); // @formatter:on }
修正後
@Bean public Job csv2dbJob() { // @formatter:off return jobBuilderFactory .get("csv2dbJob") .listener(logListener) .start(fileExistCheckStep()) .on(FileExistCheckTasklet.NOT_EXIST).end() .from(fileExistCheckStep()) .next(masterDeleteStep()) .next(csv2dbStep()) .build() .build(); // @formatter:on }
SpringBatchの条件分岐を利用したJobに変更しました。
ファイルが存在しない場合に設定したExitStatusをチェックし、
NOT_EXISTの場合はJobを終了します。
この時、masterDeleteStep、csv2dbStepは実行されません。
フローはこんな感じです
これで、その6で上げた不満点は、全て解消されました。
現在、私の中でSpringBatchよりもWindowsのUWPアプリ開発の優先度が高いので、
気分転換に書くかもですが、SpringBatchは一旦、ここまでとします。