はじめに
Jdbc系のItemReader/ItemWriterを利用して簡単なバッチアプリを作ってみたので、JdbcPagingItemReader/JdbcCursorItemReader/JdbcBatchItemWriterの実装例をまとめてみました。
Spring Bacthのバージョンは4.0.1です。
サンプルAPの仕様
単純なデータをコピーするだけのバッチAPです。
テーブルsampleのデータを取得し、同じ構造のテーブルsample_subに出力するだけです。サンプルAPではH2DBをDBMSとして利用します。
テーブル定義は以下の通りです。
CREATE TABLE IF NOT EXISTS sample (
id VARCHAR(4),
parameter1 VARCHAR(20),
parameter2 VARCHAR(20),
status VARCHAR(10),
last_update_timestamp TIMESTAMP,
PRIMARY KEY(id)
);
CREATE TABLE IF NOT EXISTS sample_sub (
id VARCHAR(4),
parameter1 VARCHAR(20),
parameter2 VARCHAR(20),
status VARCHAR(10),
last_update_timestamp TIMESTAMP,
PRIMARY KEY(id)
);
実装サンプル
JdbcPagingItemReader
JdbcPagingItemReaderを実装する場合、queryProviderを設定する必要があり、実装方法はSqlPagingQueryProviderFactoryBeanを利用するパターンと、各DBMSごとに提供されているPagingQueryProviderを利用するパターンの2つあります。
(サンプルAPではH2DBをりようしているため、H2PagingQueryProviderを利用します。利用するDBMSによって指定するクラスが異なります。PagingQueryProviderのクラス一覧はこちら参照。)
SqlPagingQueryProviderFactoryBeanの利用例
@Autowired
public DataSource dataSource;
@Bean
public SqlPagingQueryProviderFactoryBean queryProvider() {
SqlPagingQueryProviderFactoryBean provider = new SqlPagingQueryProviderFactoryBean();
provider.setDataSource(dataSource);
provider.setSelectClause("SELECT id, parameter1, parameter2, status, last_update_timestamp");
provider.setFromClause("FROM sample");
provider.setWhereClause("WHERE status = :status");
provider.setSortKey("id");
return provider;
}
@Bean
public JdbcPagingItemReader jdbcPagingItemReader() throws Exception {
Map<String, Object> parameterValues = new HashMap();
parameterValues.put("status", "A");
return new JdbcPagingItemReaderBuilder<Sample>()
.name("jdbcPagingItemReader")
.dataSource(dataSource)
.queryProvider(queryProvider().getObject())
.parameterValues(parameterValues)
.rowMapper(new SampleRowMapper())
.pageSize(1000)
.build();
}
H2PagingQueryProviderの利用例
@Autowired
public DataSource dataSource;
@Bean
public H2PagingQueryProvider h2QueryProvider(Map sortKeys) {
H2PagingQueryProvider h2Provider = new H2PagingQueryProvider();
h2Provider.setSelectClause("SELECT id, parameter1, parameter2, status, last_update_timestamp");
h2Provider.setFromClause("FROM sample");
h2Provider.setWhereClause("WHERE status = :status");
h2Provider.setSortKeys(sortKeys);
return h2Provider;
}
@Bean
public JdbcPagingItemReader jdbcPagingItemReader() {
Map<String, Order> sortKeys = new HashMap(1);
sortKeys.put("id", Order.ASCENDING);
Map<String, Object> parameterValues = new HashMap();
parameterValues.put("status", "A");
return new JdbcPagingItemReaderBuilder<Sample>()
.name("jdbcPagingItemReader")
.dataSource(dataSource)
.queryProvider(h2QueryProvider(sortKeys))
.parameterValues(parameterValues)
.rowMapper(new SampleRowMapper())
.pageSize(1000)
.build();
}
JdbcCursorItemReader
@Autowired
public DataSource dataSource;
@Bean
public JdbcCursorItemReader jdbcCursorItemReader() {
String status = "A";
return new JdbcCursorItemReaderBuilder<Sample>()
.dataSource(dataSource)
.name("jdbcCursorItemReader")
.sql("SELECT id, parameter1, parameter2, status, last_update_timestamp FROM sample WHERE status = '" + status + "';")
.rowMapper(new SampleRowMapper())
.build();
}
JdbcBatchItemWriter
@Bean
public JdbcBatchItemWriter jdbcBatchItemWriter() {
return new JdbcBatchItemWriterBuilder<Sample>()
.dataSource(dataSource)
.itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<Sample>())
.sql("INSERT INTO sample_sub (id, parameter1, parameter2, status, last_update_timestamp) VALUES (:id, :parameter1, :parameter2, :status, :lastUpdateTimestamp);")
.build();
}
その他クラス
ItemReader/ItemWriterで参照するその他クラスはこちらです。
public class Sample {
private String id;
private String parameter1;
private String parameter2;
private String status;
private Timestamp lastUpdateTimestamp;
/*setter・getterは省略*/
}
@Component
public class SampleRowMapper implements RowMapper {
@Override
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
Sample sample = new Sample();
sample.setId(rs.getString("id"));
sample.setParameter1(rs.getString("parameter1"));
sample.setParameter2(rs.getString("parameter2"));
sample.setStatus(rs.getString("status"));
sample.setLastUpdateTimestamp(rs.getTimestamp("last_update_timestamp"));
return sample;
}
}
おまけ (Spring Batch 3.0.xでの実装)
Spring Batch 4.0.xの公式ドキュメントの実装例では、Builderを利用してItemReader/ItemWriterを実装していますが、Spring Batch 3.0.xではBuilderが提供されていないため、今回の実装例は利用できません。
Spring Batch 3.0.xを利用する場合は、Builderを利用せずに実装する必要があります。
JdbcPagingItemReader
@Bean
public ItemReader<Sample> jdbcPagingItemReader() throws Exception {
Map<String, Object> parameterValues = new HashMap();
parameterValues.put("status", "A");
JdbcPagingItemReader reader = new JdbcPagingItemReader();
reader.setDataSource(dataSource);
reader.setPageSize(1000);
reader.setRowMapper(new SampleRowMapper());
reader.setParameterValues(parameterValues);
reader.setQueryProvider(queryProvider().getObject());
return reader;
}
JdbcCursorItemReader
@Bean
public ItemReader<Sample> jdbcCursorItemReader() {
String status = "A";
JdbcCursorItemReader reader = new JdbcCursorItemReader();
reader.setDataSource(dataSource);
reader.setSql("SELECT id, parameter1, parameter2, status, last_update_timestamp FROM sample WHERE status = '" + status + "';");
reader.setRowMapper(new SampleRowMapper());
return reader;
}
JdbcBatchItemWriter
@Bean
public ItemWriter<Sample> jdbcBatchItemWriter(){
JdbcBatchItemWriter writer = new JdbcBatchItemWriter();
writer.setDataSource(dataSource);
writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<Sample>());
writer.setSql("INSERT INTO sample_sub (id, parameter1, parameter2, status, last_update_timestamp) VALUES (:id, :parameter1, :parameter2, :status, :lastUpdateTimestamp);");
return writer;
}