Springのチュートリアルページをもとに、Spring Boot + Spring Batchで簡単なバッチサービスを作ってみました。具体的には、CSVファイルを読み込み、ファイル内の文字列を加工してデータベースに格納するバッチです。今回使用するデータベース(HSQLDB)はメモリ上で利用するものなので、事前にMySQLやOracleといったクライアントを用意する必要はありません。
環境
準備
まずは作業用のディレクトリを作成し、そのディレクトリに移動します。
以下のようなディレクトリ構造になっているはずです。
続いて、build.gradle
を作成します。依存性にSpring BatchとHSQLDBを指定しているのがポイントです。
build.gradle
データを作成する
インプットファイルとなるCSVファイルを作成します。first name(名), last name(姓)の順に並んでいます。
src/main/resources/sample-data.csv
テーブルを作成するためのSQLスクリプトを作成します。さきほど作成したCSVデータを格納する用のテーブルですね。
src/main/resources/schema-all.sql
ちなみにSpring Bootでは、src/main/resources
直下にschema.sql
やdata.sql
を配備することで、起動時にDDLやDMLを自動で実行してくれます。OracleやMySQLといったデータベースプラットフォーム形式のSQL文を実行したい場合は、schema-oracle.sql
やdata-mysql.sql
のように指定してやればOKです。今回のschema-all.sql
のように-all
をつけることでどのプラットフォームでも実行されるようになります。
ビジネスクラスを作成する
CSVファイルの1レコードに対応するクラスを作成します。
src/main/java/hello/Person.java
中間処理を作成する
ファイル内のfirst name(名), last name(姓)を大文字に加工するクラスを作成します。一連のバッチ処理の「CSVファイルを読み込む→中間処理を行う→データベースに格納する」の中の「中間処理を行う」がこのクラスの役割です。
src/main/java/hello/PersonItemProcessor.java
このクラスはSpring BatchのItemProcessor
インタフェースを実装しています。この実装により、後述するバッチジョブ内のコードが簡単に書けるようになります。
バッチジョブをまとめる
このクラスで実際のバッチジョブをまとめていきます。Spring Batchにはビジネスロジックに集中するための便利なユーティリティクラスが用意されているようです。
src/main/java/hello/BatchConfiguration.java
@EnableBatchProcessing
アノテーションをつけることで、ジョブをサポートする多くのBean(Springが管理するインスタンス)が使えるようになります。
コードが長いので細分化して見ていきます。まずは、「CSVファイルを読み込む」、「中間処理を行う」、「データベースに格納する」の部分です。
reader
はItemReader
を生成します。これは、sample-data.csv
を探し出し、CSVファイル内の1行ずつをPerson
オブジェクトに変換します。
processor
は先ほど作成した中間処理クラスであるPersonItemProcessor
のインスタンスを生成します。姓名を大文字に変換するやつですね。
writer
はItemWriter
を生成します。@EnableBatchProcessing
の機能を使って、メモリ上のデータベース内のテーブルに出力内容を書き込んでいます。
ここからはジョブの定義について見ていきます。
1つめのメソッドはジョブを定義し、2つめのメソッドはステップを定義しています。Spring Batchでは、ジョブはステップから構成されます。各ステップにはreader
, processor
, writer
が含まれています。
ジョブ定義では、実行状態を維持するデータベースを使用するためにincrementer
が必要なようです。flow
で実行するステップを定義しています。
ステップ定義では、一度に書き込むデータ量を定義しています。 今回の場合、一度に最大10個のレコードを書き込みます(chunk(10)
)。あとは、 reader
, processor
, writer
を定義してやればOKです。
ちなみに、<Person,Person>
の箇所は、インプットとアウトプットの型を表しています。今回の場合、インプットがItemReader<Person>
で、アウトプットがItemWriter<Person>
にあたります。
以上で長かったコードの説明は終了です。
おまけとして、バッチ処理が完了した際に動作するリスナークラスを作成します。
src/main/java/hello/JobCompletionNotificationListener.java
アプリケーションを実行可能にする
Spring Bootを起動するクラスを作成してやればバッチサービスの出来上がりです!
src/main/java/hello/Application.java
あとは、ビルドして実行するだけです。以下のようにデータが書き込まれ、バッチ完了時のリスナーログが出力されていればOKです。
お疲れさまでしたー。
まとめ
Spring Bootで簡単なバッチサービスを作ってみた感想としては、「フレームワーク化されていて使いやすそう」でした。あと、公式のチュートリアルだけに説明がわかりやすく理解しやすかったです。実際に手を動かしてみるとより理解が深まったので、本記事やチュートリアルを参考にバッチサービスを作ってみてはいかがでしょうか。
Spring Batchも良さげですが、個人的にはCommandLineRunner
を使った方法の方がシンプルで好きです。CommandLineRunner
については以下の記事でまとめています。
Spring Bootで簡単なコマンドラインアプリケーションを作成してみる - Reasonable Code