「Spring Batch 入門ガイド」を実用化する2
目的
「Spring Batch入門ガイド(バッチサービスの作成)」を基に、追加要件を組み込むことで、より実用的なバッチプログラムの作成方法を解説します。
背景
「Spring Batch入門ガイド」のサンプルプログラムにあるBatchConfiguration
クラスは、step1
のリーダーとライターの実装を含んでおり、プロセッサーはPersonItemProcessor
クラスにあります。
ステップ数が増えた場合、ステップごとにクラスを分けた方が管理しやすくなります。また、チャンク志向のステップでは、リーダー、プロセッサー、ライターを一つのクラスにまとめた方が理解しやすくなります。
要件
背景を踏まえて、以下の要件を設定しました。
-
step1
のリーダー、プロセッサー、ライターを一つのクラスにまとめる -
BatchConfiguration
クラスを設定クラスにするため簡素化する
これらの要件を満たすために、「Spring Batch入門ガイド」のサンプルプログラムを修正および追加します。
1. リーダー、プロセッサー、ライターを一つのクラスにまとめる
BatchConfiguration
クラスをコピーし、クラス名をStep1Configuration
に変更します。
importUserJob
、step1
メソッドは削除します。
@Configuration
public class Step1Configuration {
@Bean
public FlatFileItemReader<Person> reader() {
return new FlatFileItemReaderBuilder<Person>()
.name("personItemReader")
.resource(new ClassPathResource("sample-data.csv"))
.delimited()
.names("firstName", "lastName")
.targetType(Person.class)
.build();
}
@Bean
public PersonItemProcessor processor() {
return new PersonItemProcessor();
}
@Bean
public JdbcBatchItemWriter<Person> writer(DataSource dataSource) {
return new JdbcBatchItemWriterBuilder<Person>()
.sql("INSERT INTO people (first_name, last_name) VALUES (:firstName, :lastName)")
.dataSource(dataSource)
.beanMapped()
.build();
}
}
ただし、PersonItemProcessor
クラスはそのままとします。
2. 設定クラスにするため簡素化する
BatchConfiguration
クラスは、reader
、processor
、writer
メソッドは削除します。
@Configuration
public class BatchConfiguration {
@Bean
public Job importUserJob(JobRepository jobRepository,Step step1, JobCompletionNotificationListener listener) {
return new JobBuilder("importUserJob", jobRepository)
.listener(listener)
.start(step1)
.build();
}
@Bean
public Step step1(JobRepository jobRepository, DataSourceTransactionManager transactionManager,
FlatFileItemReader<Person> reader, PersonItemProcessor processor, JdbcBatchItemWriter<Person> writer) {
return new StepBuilder("step1", jobRepository)
.<Person, Person> chunk(3, transactionManager)
.reader(reader)
.processor(processor)
.writer(writer)
.build();
}
}
以上で、要件を満たしました。
更新・追加ソースファイル
「Spring Batch入門ガイド」のサンプルプログラムに加えた、更新および追加のファイルは以下の通りです。
└── src
└── main
└── java
└── com.example.batchprocessing
├── BatchConfiguration.java(更新)
└── Step1Configuration.java(追加)
参考
今回の要件は、単純にクラス分けをすれば実現できましたが、それに気づくまでは、ItemReader
、ItemProcessor
、ItemWriter
をインターフェースしたクラスを実装することで実現していました。
以前の方法
1. リーダー、プロセッサー、ライターを一つのクラスにまとめる
既存のPersonItemProcessor
クラスは、プロセッサーのみを定義していますが、このクラスにリーダーとライターの定義も加えて、step1
の実装を集約します。
まず、クラス名をPersonItemProcessor
からPersonItemHandler
に変更します。
その上で、ItemReader
とItemWriter
をインターフェースします。
public class PersonItemHandler implements ItemProcessor<Person, Person>, ItemReader<Person>, ItemWriter<Person> {
リーダーとライターの実装のために、reader
、writer
フィールドを追加します。
private final FlatFileItemReader<Person> reader;
private final JdbcBatchItemWriter<Person> writer;
また、コンストラクタを追加し、リーダーとライターの初期化をします。
public PersonItemHandler(DataSource dataSource) {
this.reader = new FlatFileItemReaderBuilder<Person>()
.name("personItemReader")
.resource(new ClassPathResource("sample-data.csv"))
.delimited()
.names("firstName", "lastName")
.targetType(Person.class)
.build();
reader.open(new ExecutionContext());
this.writer = new JdbcBatchItemWriterBuilder<Person>()
.sql("INSERT INTO people (first_name, last_name) VALUES (:firstName, :lastName)")
.dataSource(dataSource)
.beanMapped()
.build();
writer.afterPropertiesSet();
}
FlatFileItemReaderBuilder
、JdbcBatchItemWriterBuilder
文は、BatchConfiguration
クラスにあるコードと同様ですが、それぞれ、以下を追加します。
reader.open(new ExecutionContext());
writer.afterPropertiesSet();
最後に、インターフェースの実装です。
@Override
public void write(Chunk<? extends Person> chunk) throws Exception {
writer.write(chunk);
}
@Override
public Person read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
return reader.read();
}
2. 設定クラスにするため簡素化する
BatchConfiguration
クラスから、reader
、processor
、writer
メソッドは削除します。
次に、1.で作成したPersonItemHandler
を@Bean
アノテーションを使って定義します。
@Bean
public PersonItemHandler personItemHandler(DataSource dataSource) {
return new PersonItemHandler(dataSource);
}
最後に、step1
メソッドでpersonItemHandler
を使用するように変更します。
@Bean
public Step step1(JobRepository jobRepository, DataSourceTransactionManager transactionManager,
PersonItemHandler personItemHandler) {
return new StepBuilder("step1", jobRepository)
.<Person, Person> chunk(3, transactionManager)
.reader(personItemHandler)
.processor(personItemHandler)
.writer(personItemHandler)
.build();
}
以上で、すべての要件を満たしました。
まとめ
1. リーダー、プロセッサー、ライターを一つのクラスにまとめる
PersonItemHandler
クラスでは、Spring BatchのItemReader
、ItemProcessor
、およびItemWriter
インターフェイスを実装し、これらの機能を一つのクラスに統合しています。これにより、データの読み込み、処理、書き込みのロジックが一箇所に集約され、ステップの管理が容易になります。
2. 設定クラスにするため簡素化する
BatchConfiguration
クラスの役割を、ジョブおよびステップの定義に限定します。これにより、具体的なビジネスロジック(読み込み、処理、書き込み)はPersonItemHandler
に委ねられ、BatchConfiguration
は設定と構成に集中できるようになります。
更新・追加ソースファイル
「Spring Batch入門ガイド」のサンプルプログラムに加えた、更新および追加のファイルは以下の通りです。
└── src
└── main
└── java
└── com.example.batchprocessing
├── BatchConfiguration.java(更新)
├── PersonItemHandler.java(追加)
└── PersonItemProcessor.java(削除)
最後に
このような構成は、一般的なSpring Batchアプリケーションの設計パターンとは異なる可能性がありますこと、ご了承ください。
コード
Discussion