簡単なSpring Batchのサンプル

概要

Spring BatchJobという単位でバッチ処理を行います。
Jobは複数のStepを順番に実行します。
Stepには入力、処理、出力をひとまとまりに実行するChankと自由に処理を実行できるTaskletというふたつの種類があります。

0001_Jobの構成

多くのバッチ処理はどこからかデータを読み込み加工してどこかへ出力するという形になります。
データベースに出力するChankでは出力をトランザクションで保護します。
途中でエラーが発生した場合はロールバックされ処理が正常に終了した場合はコミットされます。

データベースのテーブルからデータを読み込み別テーブルに出力する最も簡単なバッチ処理を実装します。
このサンプルはSpring Batchの構造を紹介する目的で作成しています。
行っている処理に意味はありません。
サンプルではMySQLを使用していますがJDBCで接続できるデータベースであれば何でも構いません。

データベースの作成

次のコマンドを使用してデータベースを作成します。
ついでにテスト用のユーザーも作成します。

CREATE DATABASE sample_db;
CREATE USER sample_user IDENTIFIED BY 'sample_password';
GRANT ALL PRIVILEGES ON sample_db.* TO sample_user;

mysqlコマンドでデータベースに接続します。

mysql -u sample_user -p sample_db

次のSQLを用いてテーブルを作成します。

CREATE TABLE IF NOT EXISTS source_item (
name VARCHAR(100) NOT NULL PRIMARY KEY,
value VARCHAR(200) NOT NULL,
valid BOOLEAN
);
CREATE TABLE IF NOT EXISTS target_item (
name VARCHAR(100) NOT NULL PRIMARY KEY,
value VARCHAR(200) NOT NULL
);
CREATE TABLE IF NOT EXISTS large_item (
name VARCHAR(100) NOT NULL PRIMARY KEY,
value VARCHAR(200) NOT NULL
);

Step-1

Step-1source_itemテーブルから読み込みvalidtrueのレコードだけをtarget_itemに出力します。

ItemReader

source_itemから読み込むItemReaderを実装します。
処理の大部分はフレームワークが行うのでプログラムではエンティティとリポジトリを実装します。

  • SourceItemEntity.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 = "source_item")
    public class SourceItemEntity {
    @Id
    @Column(name = "name", nullable = false)
    @Getter
    private String name;
    @Column(name = "value", nullable = false)
    @Getter
    private String value;
    @Column(name = "valid", nullable = false)
    @Getter
    private boolean valid;
    public SourceItemEntity(
    String name,
    String value,
    boolean valid) {
    this.name = name;
    this.value = value;
    this.valid = valid;
    }
    }
    

  • SourceItemRepository.java

    package com.sios.ex.springbatch;
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.stereotype.Repository;
    @Repository
    public interface SourceItemRepository extends JpaRepository<SourceItemEntity, String> {
    }
    

作成したエンティティとリポジトリを用いてItemReaderを組み立てます。

  • SpringBatchSample1Configuration.javaより抜粋
    @Autowired
    private SourceItemRepository sourceItemRepository;
    ・
    ・
    ・
    @Bean
    public ItemReader<SourceItemEntity> sourceItemReader() {
    RepositoryItemReader<SourceItemEntity> reader = new RepositoryItemReader<>();
    reader.setRepository(sourceItemRepository);
    reader.setMethodName("findAll");
    Map<String, Direction> sort = new HashMap<>();
    sort.put("name", Direction.ASC);
    reader.setSort(sort);
    return reader;
    }
    

ItemProcessor

ItemProcessorsource_itemvalidtrueのレコードだけをTargetItemEntityのオブジェクトに変換して返します。
target_itemに出力しない場合はnullを返します。

  • TargetItemProcessor.java
    package com.sios.ex.springbatch;
    import org.springframework.batch.item.ItemProcessor;
    public class TargetItemProcessor implements ItemProcessor<SourceItemEntity, TargetItemEntity> {
    @Override
    public TargetItemEntity process(SourceItemEntity item) throws Exception {
    if (item.isValid()) {
    return new TargetItemEntity(item.getName(), item.getValue());
    } else {
    return null;
    }
    }
    }
    

  • SpringBatchSample1Configuration.javaより抜粋

    @Bean
    public TargetItemProcessor targetItemProcessor() {
    return new TargetItemProcessor();
    }
    

ItemWriter

target_itemへ出力するItemWriterを実装します。
処理の大部分はフレームワークが行うのでプログラムではエンティティとリポジトリを実装します。

  • 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(
    String name,
    String value) {
    this.name = name;
    this.value = value;
    }
    }
    

  • TargetItemRepository.java

    package com.sios.ex.springbatch;
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.stereotype.Repository;
    @Repository
    public interface TargetItemRepository extends JpaRepository<TargetItemEntity, String> {
    }
    

  • SpringBatchSample1Configuration.javaより抜粋

    @Autowired
    private TargetItemRepository targetItemRepository;
    ・
    ・
    ・
    @Bean
    public ItemWriter<TargetItemEntity> targetItemWriter() {
    RepositoryItemWriter<TargetItemEntity> writer = new RepositoryItemWriter<>();
    writer.setRepository(targetItemRepository);
    writer.setMethodName("save");
    return writer;
    }
    

Stepの構築

  • SpringBatchSample1Configuration.javaより抜粋
    @Autowired
    private StepBuilderFactory stepBuilderFactory;
    ・
    ・
    ・
    @Bean
    public Step sampleBatch1Step1() {
    return stepBuilderFactory.get("sampleBatch1Step1")
    .<SourceItemEntity, TargetItemEntity> chunk(Integer.MAX_VALUE)
    .reader(sourceItemReader())
    .processor(targetItemProcessor())
    .writer(targetItemWriter())
    .build();
    }
    

Step-2

Step-2target_itemテーブルから読み込み英字を大文字に変換してlarge_itemテーブルに出力します。

ItemReader

Step-1ItemReaderのエンティティとリポジトリが変わっただけなので省略します。

ItemProcessor

受け取ったTargetItemEntitynamevalueの値を大文字に変換してLargetItemEntityのオブジェクトを生成して返します。

package com.sios.ex.springbatch;
import org.springframework.batch.item.ItemProcessor;
public class LargeItemProcessor implements ItemProcessor<TargetItemEntity, LargeItemEntity> {
@Override
public LargeItemEntity process(TargetItemEntity item) throws Exception {
return new LargeItemEntity(
item.getName().toUpperCase(),
item.getValue().toUpperCase());
}
}
* SpringBatchSample1Configuration.javaより抜粋
@Bean
public LargeItemProcessor largeItemProcessor() {
return new LargeItemProcessor();
}

ItemWriter

Step-1ItemWriterのエンティティとリポジトリが変わっただけなので省略します。

Jobの組み立て

Step-1Step-2のふたつのStepを持つJobを構築します。

  • SpringBatchSample1Configuration.javaより抜粋
    @Autowired
    private JobBuilderFactory jobBuilderFactory;
    ・
    ・
    ・
    @Bean
    public Job sampleBatch1Job() {
    return jobBuilderFactory.get("sampleBatch1Job")
    .incrementer(new RunIdIncrementer())
    .flow(sampleBatch1Step1())
    .next(sampleBatch1Step2())
    .end()
    .build();
    }
    

Jobの実行

最後にJobを実行するメインクラスを作成します。
SpringBatchSample1Application#mainを呼び出すとバッチ処理を行います。

package com.sios.ex.springbatch;
import org.springframework.batch.core.launch.support.CommandLineJobRunner;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
@SpringBootApplication
public class SpringBatchSample1Application implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(SpringBatchSample1Application.class);
application.setWebApplicationType(WebApplicationType.NONE);
ApplicationContext context = application.run();
SpringApplication.exit(context);
}
@Override
public void run(String... args) throws Exception {
CommandLineJobRunner.main(new String[] {
"com.sios.ex.springbatch.SpringBatchSample1Configuration",
"sampleBatch1Job"});
}
}

ソースファイル一式は次のリンクからダウンロードできます。
ソースファイル一式

ご覧いただきありがとうございます! この投稿は役に立ちましたか? 役に立った 役に立たなかった

Be the first to comment

コメント投稿

Your email address will not be published.


*