#はじめに
tsvファイルをresouse配下に置き、SpringBootのバッチ処理でPostgresのテーブルに取り込みを行う機能を作成したい。
#環境
- macOS Big Sur 11.2.3
- Java8
- SpringBoot Maven
- PostgreSQL
#pom.xml
Spring Batchを依存性に追加する
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>
#テーブル作成
src/main/resources/schema-all.sql
DROP TABLE if EXISTS items;
create table items (
id serial not null
, name character varying(255)
, condition integer
, category integer
, brand character varying(255)
, price double PRECISION
, shipping integer
, description text
, constraint items_PKC primary key (id)
);
Spring Bootでは、src/main/resources直下にschema.sqlやdata.sqlを配備することで、起動時にDDLやDMLを自動で実行してくれます。
また、-allをつけることでどのプラットフォームでも(OracleやMySQLなど)実行されるようになります。
#ビジネスクラスの作成
TSVファイルの1レコードに対応するクラスを作成します。
public class Item {
private Integer id;
private String name;
private Integer condition;
private Integer category;
private String brand;
private Integer price;
private Integer shipping;
private String description;
#バッジジョブをまとめる
@EnableBatchProcessingアノテーションをつけることで、Bean(Springが管理しているインスタンス)が使えるようになります。
@Configuration
@EnableBatchProcessing
public class BatchConfiguration {
@Autowired
public JobBuilderFactory jobBuilderFactory;
@Autowired
public StepBuilderFactory stepBuilderFactory;
// tag::readerwriterprocessor[]
@Bean
public FlatFileItemReader<Item> reader() {
//ItemReaderを生成します。
//demo.tsvを探し出し、CSVファイル内の1行ずつをItemオブジェクトに変換します。
return new FlatFileItemReaderBuilder<Item>()
.name("ItemReader")
.resource(new ClassPathResource("demo.tsv"))
.linesToSkip(1) //ヘッダーをスキップ
.delimited()
.delimiter("\t") //タブ区切りを指定)
.names(new String[]{"id","name","condition","category","brand","price","shipping","description"})
.fieldSetMapper(new BeanWrapperFieldSetMapper<Item>() {{
setTargetType(Item.class);
}})
.build();
}
@Bean
public JdbcBatchItemWriter<Item> writer(DataSource dataSource) {
return new JdbcBatchItemWriterBuilder<Item>()
.itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
.sql("INSERT INTO items (id,name,condition,category,brand,price,shipping,description) "
+ " VALUES (:id, :name, :condition, :category, :brand, :price, :shipping, :description )")
.dataSource(dataSource)
.build();
}
// tag::jobstep[]
@Bean
public Job importItemJob(Step step1) {
return jobBuilderFactory.get("importItemJob") //Job名を指定
.incrementer(new RunIdIncrementer())
.flow(step1) //実行するStepを指定
.end()
.build();
}
@Bean
public Step step1(JdbcBatchItemWriter<Item> writer) {
//inputはItemReader<Item>で、outputがItemWriter<Item>
//10レコードずつ書き込む
return stepBuilderFactory.get("step1") //Step名を指定
.<Item, Item> chunk(10)
.reader(reader())
.writer(writer)
.build();
}
// end::jobstep[]
readerはItemReaderを生成します。これは、demo.tsvを探し出し、TSVファイル内の1行ずつをItemオブジェクトに変換します。
writerはItemWriterを生成します。データベース内のテーブルに出力内容を書き込んでいます。
#バッチの起動設定
spring:
datasource:
url: jdbc:postgresql://localhost:5432/DB名
username: user
password: pass
driver-class-name: org.postgresql.Driver
batch:
initialize-schema: always
job:
enabled: false
"initialize-schema: always"
SpringBatchが使用するテーブルのDDLを実行するための設定。デフォルトではembeddedで、PostgreSQLを使用する場合はDDLが実行されないので、明示的に変更しておく。
"enabled: false "
デフォルトではtrueでSpring起動時にJobが実行されるが、起動時はJobParametersがないため起動時には実行できない。そのため明示的に変更しておく。