ããã¯ããªã«ãããããŠæžãããã®ïŒ
Spring Batchã«ã€ããŠãã¡ãã£ãšèŠãŠãããããªããšããããšã§ã
Spring Batch
Spring Batchã®ããŒãžã¯ãã¡ãã
https://spring.io/projects/spring-batch
ããã¥ã¡ã³ãã
Spring Batch - Reference Documentation
ãŸãã¯ãã€ã³ãããã¯ã·ã§ã³ãèªãã§ã¿ãŸãããã
Spring Batchãç»å Žããããã¯ã°ã©ãŠã³ãã«ã€ããŠã
Spring Batch Introduction / Background
OSSãé¢é£ããã³ãã¥ããã£ã¯ãWebããŒã¹ãMicroservicesããŒã¹ã®ã¢ãŒããã¯ãã£ãŒã«å€§ãã泚ç®ããŠããŸããããããåŠçã«é¢ããŠã¯
ããã§ããããŸããããããã«ã¯æšæºçã§åå©çšå¯èœãªã¢ãŒããã¯ãã£ãŒããªãããããšã³ã¿ãŒãã©ã€ãºITã§ã¯1åéãã®ç€Ÿå
ãœãªã¥ãŒã·ã§ã³ã
å€ãäœãåºãããŠããŸãã
While open source software projects and associated communities have focused greater attention on web-based and microservices-based architecture frameworks, there has been a notable lack of focus on reusable architecture frameworks to accommodate Java-based batch processing needs, despite continued needs to handle such processing within enterprise IT environments. The lack of a standard, reusable batch architecture has resulted in the proliferation of many one-off, in-house solutions developed within client enterprise IT functions.
ãã®ç¶æ³ã«å¯ŸããŠãSpringSourceãšAccentureãååããŠSpring Batchãã§ããããã§ãã
ã©ãããæã«äœ¿ãã®ãïŒãšãããšããã§ããã
Spring Batch Introduction / Usage Scenarios
äžè¬ã«ããããããã°ã©ã ã¯æ¬¡ã®ãããªããšãè¡ããŸãã
- å€æ°ã®ã¬ã³ãŒããããŒã¿ããŒã¹ããã¡ã€ã«ããŸãã¯ãã¥ãŒããèªã¿åã
- ããŒã¿ã«å¯ŸããŠããªã«ãåŠçããã
- ãã©ãŒããããå€æŽããããŒã¿ãæžãæ»ã
Spring Batchã¯ããã®åºæ¬çãªãããã®ç¹°ãè¿ããèªååãããã®ã§ã以äžã®ãããªã·ãŒã³ã§åœ¹ã«ç«ã¡ãŸãã
- ãããåŠçã®å®æçãªã³ããã
- 䞊è¡ã䞊åãããåŠç
- ã¡ãã»ãŒãžé§ååŠç
- é害åŸã®æåãŸãã¯ã¹ã±ãžã¥ãŒã«ãããåèµ·å
- äŸåããã¹ãããã®é 次åŠç
- ã¬ã³ãŒãã®ã¹ããããªã©
- ããããµã€ãºãå°ããå Žåã®äžæ¬ãã©ã³ã¶ã¯ã·ã§ã³
Spring Batchã®ã¢ãŒããã¯ãã£ãŒã¯ãã¡ãã
Spring Batch Introduction / Spring Batch Architecture
ãªã®ã§ãããSpring Batchã®ãã¡ã€ã³ã«ãããçšèªãèŠãæ¹ãããã§ããããã
äžè¬çãªãããã®ååããã³ã¬ã€ãã©ã€ã³ãšããããã®ãããã¡ãã«æžãããŠããŸãã
Spring Batch Introduction / General Batch Principles and Guidelines
ããšãã°ã以äžã®ãããªå 容ã§ãã
- å¯èœãªéãåçŽåããåäžã®ãããã¢ããªã±ãŒã·ã§ã³ã§è€éãªæ§é ãäœãåºãããšã¯é¿ãã
- ããŒã¿ã®ä¿åå ŽæãšåŠçãè¿ãã«é 眮ããããš
- IOãæå°éã«æããã¡ã¢ãªã掻çšããããš
- ãããã2床å®è¡ããªã
- ããŒã¿ã®æŽåæ§ã«ã€ããŠã¯åžžã«ææªã®æ³å®ãè¡ããé©åãªãã§ãã¯ãšã¬ã³ãŒãã®ããªããŒã·ã§ã³ãè¡ããããŒã¿ã®æŽåæ§ãç¶æããããš
- æ©ã段éã§ãçŸå®çãªéã®ããŒã¿ãçšæããŠã¹ãã¬ã¹ãã¹ããå®æœããããš
ãããŠããããåŠçæŠç¥ã
Spring Batch Introduction / Batch Processing Strategies
ãããã®èšèšãšå®è£ ã¯ã以äžã®æšæºçãªæ§æèŠçŽ ããè¡ããããã«ãã¹ãã§ãã
- å€æã¢ããªã±ãŒã·ã§ã³
- å€éšã·ã¹ãã ã«ãã£ãŠæäŸãŸãã¯çæããããã¡ã€ã«ã®çš®é¡ããšã«ãåŠçã«å¿ èŠãªæšæºãã©ãŒãããã«å€æãã
- ããªããŒã·ã§ã³ã¢ããªã±ãŒã·ã§ã³
- ãã¹ãŠã®å ¥åïŒåºåã¬ã³ãŒããæ£ãããäžè²«æ§ãããããšã確èªãã
- ããªããŒã·ã§ã³ã¯ãã¡ã€ã«ããããŒããã¬ãŒã©ãŒããã§ãã¯ãµã ãããªããŒã·ã§ã³ã¢ã«ãŽãªãºã ããããŠã¬ã³ãŒãã¬ãã«ã§ã®ã¯ãã¹ãã§ãã¯ã§è¡ã
- æœåºã¢ããªã±ãŒã·ã§ã³
- ããŒã¿ããŒã¹ããã¡ã€ã«ããã¬ã³ãŒããèªã¿åããäºåå®çŸ©ãããã«ãŒã«ã«åºã¥ããŠã¬ã³ãŒããéžæããã¡ã€ã«åºåãè¡ã
- æœåºïŒæŽæ°ã¢ããªã±ãŒã·ã§ã³
- ããŒã¿ããŒã¹ããã¡ã€ã«ããã¬ã³ãŒããèªã¿åããããŒã¿ããŒã¹ãå€æŽããããã¡ã€ã«åºåãè¡ã
- åŠçïŒæŽæ°ã¢ããªã±ãŒã·ã§ã³
- å ¥åãšãªããã©ã³ã¶ã¯ã·ã§ã³ããæœåºãæ€èšŒãè¡ããåŠçãå®è¡ãã
- ããŒã¿ããŒã¹ããå¿ èŠãªããŒã¿ãååŸãããšãšãã«ãããŒã¿ããŒã¹ã®æŽæ°ãåºååŠççšã®ã¬ã³ãŒãäœæãå«ã
- åºåïŒãã©ãŒãããã¢ããªã±ãŒã·ã§ã³
- ãã¡ã€ã«ãèªã¿èŸŒã¿ãããŒã¿ãåæ§æããŠãå°å·ãå€éšã·ã¹ãã åãã«åºåãã¡ã€ã«ãäœæãã
ãããã§ãã«ãã£ã³ã°ãããã¯ã§æ§ç¯ã§ããªãå Žåã¯ãã·ã§ã«ã¹ã¯ãªãããªã©ãäœæããå¿ èŠããããŸãã
ãŠãŒãã£ãªãã£çãªã¹ããããšããŠã¯ããœãŒããåå²ãããŒãžãšãã£ããã®ããããŸãã
ããã«ãªãã·ã§ã³ãšããŠã以äžã«ã€ããŠãæžãããŠããŸãã
- ããããŠã£ã³ããŠã§ã®åŠç
- ããããšãªã³ã©ã€ã³åŠçã®äžŠè¡æ§
- ããããšãªã³ã©ã€ã³åŠçãšã®ç«¶åãèžãŸããã楜芳çããã¯ãæ²èŠ³çããã¯ãªã©ã®æŠç¥
- 䞊ååŠç
- ããŒãã£ã·ã§ãã³ã°
- 䞊ååãšã®çµã¿åããã«ãªã
Spring Batchã«é¢ããçšèªã
- Job ⊠ãããããã»ã¹å
šäœã®ããš
- JobInstance ⊠è«ççãªJobã®å®è¡åäœãç¶æ ãæã¡ãäžæãããšããããåéããããšãã§ãã
- JobParameters ⊠Jobãéå§ããããã«äžãããã©ã¡ãŒã¿ãŒ
- JobExecution ⊠Jobå®è¡ããåäžã®æè¡çãªæŠå¿µãJobInstanceã¯æåãŸãã¯å€±æã§çµäºããå¯èœæ§ãããããå®è¡ãæ£åžžã«å®äºããªãéãã¯ãã®JobInstanceã¯å®äºãããšã¯ã¿ãªãããªã
- Step ⊠Jobã®ã·ãŒã±ã³ã·ã£ã«ãªãã§ãŒãºãã«ãã»ã«åãããã®ããã¹ãŠã®Jobã¯ãã²ãšã€ä»¥äžã®Stepããæ§æããã
- StepExecution ⊠ããStepã®å®è¡ãè¡šçŸãããã®ãStepãå®è¡ããã床ã«ãæ°ããStepExecutionãäœæãããããŸãåã®Stepã倱æãããªã©ã®çç±ã§ãStepãèµ·åããªãéãã¯äœæãããªã
- ExecutionContext ⊠ãã¬ãŒã ã¯ãŒã¯ã«ãã£ãŠæ°žç¶åããããããŒãšå€ã®ãã¢ã®ããšãJobã®åå®è¡ã容æã«ããããšã«äœ¿ãããããã
- JobRepository ⊠JobãJobExecutionãStepãStepExecutionãExecutionContextãªã©ãäžèšã®ã¹ãã¬ãªã¿ã€ãã®æ°žç¶åã¡ã«ããºã ãJobLauncherã«å¯ŸããCRUDæäœãæäŸãã
- JobLauncher ⊠JobParametersãäžããŠJobãèµ·åããããã®ã·ã³ãã«ãªã€ã³ã¿ãŒãã§ãŒã¹
- ItemReader ⊠Stepãžã®å
¥åãšãªããã²ãšã€ã®ItemãååŸããããšãæœè±¡åãããã®ãååŸããItemããªããªã£ãå Žåã¯ã
null
ãè¿ãããšã§è¡šçŸãã - ItemWriter ⊠Stepã®åºåãšãªããããããŸãã¯Itemã®ãã£ã³ã¯ãæœè±¡åãããã®ã次ã«åãåãItemã®æ å ±ã¯ç¥ãããçŸåšã®åŒã³åºããŠæž¡ãããItemã®æ å ±ã®ã¿ãç¥ã£ãŠãã
- ItemProcessor ⊠Itemãžã®ããžãã¹åŠçãæœè±¡åãããã®ãItemReaderãã²ãšã€Itemãèªã¿åãItemWriterãæžã蟌ããŸã§ã®éã«ãItemProcessorã¯å€æããã®ä»ã®ããžãã¹åŠçãè¡ãã¢ã¯ã»ã¹ãã€ã³ããæäŸãããItemã®åŠçäžã«ãã®Itemãç¡å¹ã ãšå€å®ããå Žåã¯ã
null
ãè¿ãããšã§ãã®Itemã¯æžãåºãå¿ èŠããªãããšãè¡šã
ã¡ãªã¿ã«ãçšèªéããããŸãã
Jobã®æ§æãå®è¡ã«ã€ããŠã¯ããã¡ãã
Stepã®æ§æã«ã€ããŠã¯ããã¡ãã
ããã§ãStepã®æ§æã«ã¯ãã£ã³ã¯æåã®StepãšTaskletãšããStepã®2çš®é¡ãããããšãããããŸãã
Taskletã¯ååºã§ãããexecute
ãšããã¡ãœãããæã€Tasklet
ã€ã³ã¿ãŒãã§ãŒã¹ã䜿ã£ãŠå®è£
ãããŸãã
ãã£ã³ã¯æåã®Stepã¯ãå è¿°ã®ItemReaderãItemWriterããããŠItemProcessorããæ§æãããŸãã
ãããŠãJobå ã®Stepã¯ãããŒãæ§æããããšãã§ããŸãã
Configuring a Step / Controlling Step Flow
ãããŸã§ããåºæ¬çãªæ§æèŠçŽ ã§ããã
ããšã¯ãItemReaderãItemWriterããããŠItemProcessorã«é¢ããããã¥ã¡ã³ããã
Spring Batchã«ãããå®è£ æžã¿ã®ItemReaderãšItemWriterã®çŽ¹ä»ããããŸãã
List of ItemReaders and ItemWriters
äžè¬çãªãããã®ãã¿ãŒã³ãããã©ã³ã¶ã¯ã·ã§ã³ãšãããåŠçã®çµã¿åãããªã©ãèŠããšããããªãšæããŸãã
Batch Processing and Transactions
Spring Integrationãšçµã¿åãããããšãã§ããããã§ãã
Spring BootãšSpring Batch
âHow-toâ Guides / Batch Applications
Spring Bootã§Spring Batchã䜿ãéã«ã¯ãå€ãã®äººã質åãããããã§ãã
A number of questions often arise when people use Spring Batch from within a Spring Boot application.
- âHow-toâ Guides / Batch Applications / Specifying a Batch Data Source
- ããã©ã«ãã§ãããã¢ããªã±ãŒã·ã§ã³ã¯Jobã®è©³çŽ°ãä¿åããã®ã«ã
DataSource
ãå¿ èŠãšãã DataSource
ã¯ããã©ã«ãã§ã·ã³ã°ã«ãã³ãæ³å®ãããŠããããDataSource
ã®Beanå®çŸ©ãš@BatchDataSource
ã¢ãããŒã·ã§ã³ã䜿çšããããšã§ãè€æ°æ±ãããšãå¯èœ
- ããã©ã«ãã§ãããã¢ããªã±ãŒã·ã§ã³ã¯Jobã®è©³çŽ°ãä¿åããã®ã«ã
- âHow-toâ Guides / Batch Applications / Running Spring Batch Jobs on Startup
- Spring Batchã®Auto Configurationã¯ã
@EnableBatchProcessing
ã¢ãããŒã·ã§ã³ãä»äžããããšã§æå¹ã«ãªã - ããã©ã«ãã§ã¯ããã¹ãŠã®Jobãèµ·åãã
- èµ·åããJobãçµã蟌ãã«ã¯ã
spring.batch.job.names
ã«ã²ãšã€ããŸãã¯è€æ°ã®Jobã®ååïŒè€æ°ã®å Žåã¯ã«ã³ãåºåãïŒã§æå®ãã
- Spring Batchã®Auto Configurationã¯ã
- âHow-toâ Guides / Batch Applications / Running from the Command Line
- Spring Bootã¯
--
ããå§ãŸãã³ãã³ãã©ã€ã³åŒæ°ãããããã£ãšããŠEnvironment
ã«è¿œå ãããããããã¯Jobã«æž¡ãåŒæ°ãšããŠäœ¿çšããªãããš - ã³ãã³ãã©ã€ã³åŒæ°ããããã«æž¡ãã«ã¯ã
--
ãªãã®åœ¢åŒïŒname=value
ïŒã䜿çšããããš
- Spring Bootã¯
- âHow-toâ Guides / Batch Applications / Storing the Job Repository
- Spring Batchã«ã¯JobãªããžããªãŒã®ããã®ããŒã¿ã¹ãã¢ãå¿ èŠãããSpring Bootã䜿çšããŠããå Žåã¯æ¬ç©ã®ããŒã¿ããŒã¹ã䜿ãã¹ãã§ãã
- ã€ã³ã¡ã¢ãªãŒããŒã¿ããŒã¹ã䜿çšã¯ã§ããŠããŸã
ãŸããSpring Batchåãã®Spring Bootã®ããããã£ã¯ãããããã«ãªããŸãã
spring.batch.jdbc.initialize-schema
spring.batch.jdbc.platform
spring.batch.jdbc.schema
spring.batch.jdbc.table-prefix
spring.batch.job.enabled
spring.batch.job.names
Application Properties / Integration Properties
é·ããªããŸããããããã¥ã¡ã³ããçºããã®ã¯ãããããã«ããŠãå®éã«Spring Batchã䜿ã£ãŠãã£ãŠã¿ãŸãããã
ç°å¢
ä»åã®ç°å¢ã¯ããã¡ãã
$ java --version openjdk 17.0.2 2022-01-18 OpenJDK Runtime Environment (build 17.0.2+8-Ubuntu-120.04) OpenJDK 64-Bit Server VM (build 17.0.2+8-Ubuntu-120.04, mixed mode, sharing) $ mvn --version Apache Maven 3.8.5 (3599d3414f046de2324203b78ddcf9b5e4388aa0) Maven home: $HOME/.sdkman/candidates/maven/current Java version: 17.0.2, vendor: Private Build, runtime: /usr/lib/jvm/java-17-openjdk-amd64 Default locale: ja_JP, platform encoding: UTF-8 OS name: "linux", version: "5.4.0-109-generic", arch: "amd64", family: "unix"
ãŸããããŒã¿ããŒã¹ãšããŠã¯MySQLã䜿çšãã172.17.0.2ã§åäœããŠãããã®ãšããŸãã
$ mysql --version mysql Ver 8.0.28 for Linux on x86_64 (MySQL Community Server - GPL)
ãé¡
ä»åã¯ããã£ã³ã¯ãšTaskletã§ããããã²ãšã€ãã€Jobãäœã£ãŠã¿ãããšã«ããŸãã
- ãã£ã³ã¯
- Tasklet
- ãã£ã³ã¯ã§ç»é²ããæžç±ããŒã¿ãããã°åºåãã
ããŒã¿ããŒã¹ã¢ã¯ã»ã¹ã«ã¯JPAã䜿ããJobRepositoryã®æ°žç¶åå ãMySQLãšããŸãã
ãããžã§ã¯ããäœæãã
ãŸãã¯Spring Bootãããžã§ã¯ããäœæããŸãã
$ curl -s https://start.spring.io/starter.tgz \ -d bootVersion=2.6.7 \ -d javaVersion=17 \ -d name=batch-example \ -d groupId=org.littlewings \ -d artifactId=batch-example \ -d version=0.0.1-SNAPSHOT \ -d packageName=org.littlewings.spring.batch \ -d dependencies=batch,data-jpa,mysql \ -d baseDir=batch-example | tar zxvf -
äŸåé¢ä¿ã«ã¯ãSpring BatchãSpring Data JPAãMySQL JDBC DriverãšããŠããŸãã
ãããžã§ã¯ãå ã«ç§»åã
$ cd batch-example
MavenäŸåé¢ä¿ãããã©ã°ã€ã³ã®èšå®ã
<properties> <java.version>17</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-batch</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.batch</groupId> <artifactId>spring-batch-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
ããã©ã«ãã§äœæãããŠãããœãŒã¹ã³ãŒãã¯ãåé€ããŠãããŸãã
$ rm src/main/java/org/littlewings/spring/batch/BatchExampleApplication.java src/test/java/org/littlewings/spring/batch/BatchExampleApplicationTests.java
mainã¯ã©ã¹ã®äœæãšäžæºå
æåã«ãmainã¯ã©ã¹ãšã©ã®ãžã§ãã§ã䜿ããããªãã®ãäœæãèšå®ããŠãããŸãã
src/main/java/org/littlewings/spring/batch/App.java
package org.littlewings.spring.batch; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @EnableBatchProcessing public class App { public static void main(String... args) { SpringApplication.run(App.class, args); } }
Spring Bootã®ããã¥ã¡ã³ãã«ç¿ãã@EnableBatchProcessing
ã¢ãããŒã·ã§ã³ãä»äžããŠSpring Batchãæå¹ã«ããŸãã
âHow-toâ Guides / Batch Applications / Running Spring Batch Jobs on Startup
ããŒãã«å®çŸ©ã¯ã以äžãšããŸãã
src/main/resources/schema.sql
create table if not exists book ( isbn varchar(14), title varchar(100), price int, publish_date date, primary key(isbn) );
JPAã®ãšã³ãã£ãã£ã¯ã©ã¹ã
src/main/java/org/littlewings/spring/batch/entity/Book.java
package org.littlewings.spring.batch.entity; import java.time.LocalDate; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "book") public class Book { @Id @Column(name = "isbn") String isbn; @Column(name = "title") String title; @Column(name = "price") Integer price; @Column(name = "publish_date") LocalDate publishDate; // getterïŒsetterã¯çç¥ }
ãªããžããªãŒãSpring Data JPAã«åŸããJpaRepository
ã€ã³ã¿ãŒãã§ãŒã¹ãæ¡åŒµããŠçšæã
src/main/java/org/littlewings/spring/batch/repository/BookRepository.java
package org.littlewings.spring.batch.repository; import org.littlewings.spring.batch.entity.Book; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface BookRepository extends JpaRepository<Book, String> { }
Spring Bootã®èšå®ã
src/main/resources/application.properties
spring.datasource.url=jdbc:mysql://172.17.0.2:3306/practice?characterEncoding=utf-8&characterSetResults=utf-8&connectionCollation=utf8mb4_0900_bin spring.datasource.username=kazuhira spring.datasource.password=password spring.sql.init.mode=always spring.batch.jdbc.initialize-schema=always
ããŒã¿ããŒã¹æ¥ç¶ãšãschema.sql
ã®å®è¡ïŒspring.sql.init.mode
ïŒããã³
Spring Batchã®ã¡ã¿ããŒã¿çšã®ããŒãã«ãäœæïŒspring.batch.jdbc.initialize-schema
ïŒããããã«ããŸãã
åã蟌ãCSVãã¡ã€ã«ã¯ãããããŒãªãã®ãã®ãšæãã®ãã®ã®2ã€ãäœæã
ããããŒãªãã
src/main/resources/book.csv
978-4798142470,Spring培åºå ¥é Spring Frameworkã«ããJavaã¢ããªã±ãŒã·ã§ã³éçº,4400,2016-07-21 978-4774182179,[æ¹èšæ°ç]Springå ¥é ââJavaãã¬ãŒã ã¯ãŒã¯ã»ããè¯ãèšèšãšã¢ãŒããã¯ãã£,4180,2016-06-14 978-1492076988,Spring Boot: Up and Running: Building Cloud Native Java and Kotlin Applications,6265,2021-03-23 978-1484237236,The Definitive Guide to Spring Batch: Modern Finite Batch Processing in the Cloud,7361,2019-07-09 978-4798161488,MySQL培åºå ¥é 第4ç MySQL 8.0察å¿,4180,2020-07-06 978-4797393118,åºç€ããã®MySQL 第3ç (åºç€ããã·ãªãŒãº),6038,2017-09-22 978-4873116389,å®è·µãã€ããã©ãŒãã³ã¹MySQL 第3ç,5280,2013-11-25 978-4295000198,ããããåŠã¹ãMySQLéçšã»ç®¡çå ¥éã5.7察å¿ã,2860,2016-12-15 978-4798147406,詳解MySQL 5.7 æ¢ãŸãã¬é²åã«ä¹ãé ããªãããã®ãã¯ãã«ã«ã¬ã€ã (NEXT ONE),3960,2016-08-26 978-4774170206,MariaDB&MySQLå šæ©èœãã€ãã«,3850,2014-12-18
ããããŒããã
src/main/resources/book_with_header.csv
isbn,title,price,publishDate 978-4798142470,Spring培åºå ¥é Spring Frameworkã«ããJavaã¢ããªã±ãŒã·ã§ã³éçº,4400,2016-07-21 978-4774182179,[æ¹èšæ°ç]Springå ¥é ââJavaãã¬ãŒã ã¯ãŒã¯ã»ããè¯ãèšèšãšã¢ãŒããã¯ãã£,4180,2016-06-14 978-1492076988,Spring Boot: Up and Running: Building Cloud Native Java and Kotlin Applications,6265,2021-03-23 978-1484237236,The Definitive Guide to Spring Batch: Modern Finite Batch Processing in the Cloud,7361,2019-07-09 978-4798161488,MySQL培åºå ¥é 第4ç MySQL 8.0察å¿,4180,2020-07-06 978-4797393118,åºç€ããã®MySQL 第3ç (åºç€ããã·ãªãŒãº),6038,2017-09-22 978-4873116389,å®è·µãã€ããã©ãŒãã³ã¹MySQL 第3ç,5280,2013-11-25 978-4295000198,ããããåŠã¹ãMySQLéçšã»ç®¡çå ¥éã5.7察å¿ã,2860,2016-12-15 978-4798147406,詳解MySQL 5.7 æ¢ãŸãã¬é²åã«ä¹ãé ããªãããã®ãã¯ãã«ã«ã¬ã€ã (NEXT ONE),3960,2016-08-26 978-4774170206,MariaDB&MySQLå šæ©èœãã€ãã«,3850,2014-12-18
ãã£ã³ã¯Stepãäœæãã
ã§ã¯ããã£ã³ã¯çšã®Stepãæã€JobããäœæããŠãããŸãã
ä»åã®ãé¡ã ãšèªåã§ItemReader
ãItemWriter
ãäœæããªããŠãããã®ã§ããããŸãã¯èªåã§ãæžããŠã¿ãããšã«ããŸãã
ItemReader
ã
src/main/java/org/littlewings/spring/batch/chunk/CsvFileItemReader.java
package org.littlewings.spring.batch.chunk; import java.io.BufferedReader; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import org.littlewings.spring.batch.entity.Book; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.batch.item.file.DefaultBufferedReaderFactory; import org.springframework.batch.item.file.ResourceAwareItemReaderItemStream; import org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader; import org.springframework.core.io.Resource; public class CsvFileItemReader extends AbstractItemCountingItemStreamItemReader<Book> implements ResourceAwareItemReaderItemStream<Book> { Logger logger = LoggerFactory.getLogger(CsvFileItemReader.class); Resource resource; BufferedReader reader; DateTimeFormatter publishDateFormatter; @Override protected void doOpen() throws Exception { DefaultBufferedReaderFactory bufferedReaderFactory = new DefaultBufferedReaderFactory(); reader = bufferedReaderFactory.create(resource, "UTF-8"); publishDateFormatter = DateTimeFormatter.ofPattern("uuuu-MM-dd"); } @Override protected Book doRead() throws Exception { String line = reader.readLine(); if (line != null) { String[] tokens = line.split(","); Book book = new Book(); book.setIsbn(tokens[0]); book.setTitle(tokens[1]); book.setPrice(Integer.parseInt(tokens[2])); book.setPublishDate(LocalDate.parse(tokens[3], publishDateFormatter)); logger.info("[reader] read book: isbn = {}, title = {}", book.getIsbn(), book.getTitle()); return book; } logger.info("[reader] readed books"); return null; } @Override protected void doClose() throws Exception { reader.close(); } @Override public void setResource(Resource resource) { this.resource = resource; } }
1è¡ã®CSVèŠçŽ ãBook
ã¯ã©ã¹ã«ãããã³ã°ããç®æã¯ãæçŽã«äœæããŸãããããããŒã®èªã¿é£ã°ãã«ã¯å¯Ÿå¿ããŠããŸããã
ItemReader
ã®äœæã«ã¯ãAbstractItemCountingItemStreamItemReader
ã¯ã©ã¹ãç¶æ¿ãããšè¯ãããã§ãã
Abstract base class that provides basic restart capabilities by counting the number of items returned from an ItemReader.
List of ItemReaders and ItemWriters
ãŸããResourceAwareItemReaderItemStream
ã€ã³ã¿ãŒãã§ãŒã¹ãå®è£
ããããšã§ãSpring Batchã®ä»ã®ItemReader
ãšåãããã«
èªã¿èŸŒã¿å¯Ÿè±¡ã®ãã¡ã€ã«ãResource
ã§è¡šçŸããããã«ããŠãããŸãã
ã¡ãªã¿ã«ããã®ItemReader
ã¯ã¯ã©ã¹ã®å®çŸ©æã«ã¯Springã®BeanãšããŠã¯å®çŸ©ãããJava Configã§Springã®BeanãšããŠç»é²ããŸãã
ItemProcessor
ããã¡ãã¯ããã°åºåããã ãã«ããŸããã
LoggingBookProcessor.java
package org.littlewings.spring.batch.chunk; import org.littlewings.spring.batch.entity.Book; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.batch.item.ItemProcessor; public class LoggingBookProcessor implements ItemProcessor<Book, Book> { Logger logger = LoggerFactory.getLogger(LoggingBookProcessor.class); @Override public Book process(Book item) throws Exception { logger.info("[processor] process book: isbn = {}, title = {}", item.getIsbn(), item.getTitle()); return item; } }
ItemWriter
ã
src/main/java/org/littlewings/spring/batch/chunk/BookJpaItemWriter.java
package org.littlewings.spring.batch.chunk; import java.util.List; import org.littlewings.spring.batch.entity.Book; import org.littlewings.spring.batch.repository.BookRepository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.batch.item.support.AbstractItemStreamItemWriter; import org.springframework.beans.factory.annotation.Autowired; public class BookJpaItemWriter extends AbstractItemStreamItemWriter<Book> { Logger logger = LoggerFactory.getLogger(BookJpaItemWriter.class); @Autowired BookRepository bookRepository; @Override public void write(List<? extends Book> items) throws Exception { logger.info("[writer] write items: size = {}", items.size()); items.forEach(book -> { logger.info("[writer] write item: isbn = {}, title = {}", book.getIsbn(), book.getTitle()); bookRepository.save(book); }); } }
å
ã»ã©äœæãããBook
çšã®ãªããžããªãŒã䜿ã£ãŠããŒã¿ãããŒãã«ã«ä¿åããŸãã
ç¶æ¿ããŠããAbstractItemStreamItemWriter
ã¯ã©ã¹ã¯ãItemWriter
ããã³ItemStream
ãå®è£
ããæœè±¡ã¯ã©ã¹ã§ãä»åã¯äœ¿çšããŠããŸããã
open
ã¡ãœãããclose
ã¡ãœããããªãŒããŒã©ã€ãããŠåæåãçµäºåŠçãå®è£
ããããšãã§ããŸãã
Abstract base class that combines the ItemStream and ItemWriter interfaces.
List of ItemReaders and ItemWriters
ã§ã¯ãJobããã³Stepã®å®çŸ©ãè¡ã£ãŠãããŸãã
åç §ããã®ã¯ã以äžãããã§ããã
Configuring and Running a Job / Configuring a Job
Configuring a Step / Chunk-oriented Processing / Configuring a Step
ä»åã¯ããããªæãã§äœæã
src/main/java/org/littlewings/spring/batch/config/FileLoadToDatabaseJobConfig.java
package org.littlewings.spring.batch.config; import org.littlewings.spring.batch.chunk.BookJpaItemWriter; import org.littlewings.spring.batch.chunk.CsvFileItemReader; import org.littlewings.spring.batch.chunk.LoggingBookProcessor; import org.littlewings.spring.batch.entity.Book; import org.springframework.batch.core.Job; import org.springframework.batch.core.Step; import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; import org.springframework.batch.core.configuration.annotation.StepScope; import org.springframework.batch.core.launch.support.RunIdIncrementer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource; @Configuration public class FileLoadToDatabaseJobConfig { @Autowired JobBuilderFactory jobBuilderFactory; @Autowired StepBuilderFactory stepBuilderFactory; @Bean public Job fileLoadToDatabaseJob() { return jobBuilderFactory .get("fileLoadToDatabaseJob") .incrementer(new RunIdIncrementer()) .start(fileLoadToDatabaseStep()) .build(); } @Bean public Step fileLoadToDatabaseStep() { return stepBuilderFactory .get("fileLoadToDatabaseStep") .<Book, Book>chunk(3) .reader(csvFileItemReader(null)) .processor(loggingBookProcessor()) .writer(bookJpaItemWriter()) .build(); } @StepScope @Bean public CsvFileItemReader csvFileItemReader(@Value("#{jobParameters['filePath']}") String filePath) { Resource fileResource = new FileSystemResource(filePath); CsvFileItemReader itemReader = new CsvFileItemReader(); itemReader.setResource(fileResource); itemReader.setName("csvFileItemReader"); itemReader.setSaveState(false); return itemReader; } @StepScope @Bean public LoggingBookProcessor loggingBookProcessor() { return new LoggingBookProcessor(); } @StepScope @Bean public BookJpaItemWriter bookJpaItemWriter() { return new BookJpaItemWriter(); } }
ãããŸã§ã«äœæãããItemReader
ãItemProcessor
ãItemWriter
ã®Beanå®çŸ©ããããã@StepScope
ãšããŠããŸãã
@StepScope @Bean public CsvFileItemReader csvFileItemReader(@Value("#{jobParameters['filePath']}") String filePath) { Resource fileResource = new FileSystemResource(filePath); CsvFileItemReader itemReader = new CsvFileItemReader(); itemReader.setResource(fileResource); itemReader.setName("csvFileItemReader"); itemReader.setSaveState(false); return itemReader; } @StepScope @Bean public LoggingBookProcessor loggingBookProcessor() { return new LoggingBookProcessor(); } @StepScope @Bean public BookJpaItemWriter bookJpaItemWriter() { return new BookJpaItemWriter(); }
èªã¿èŸŒããã¡ã€ã«ã¯ãJobParameter
ãšããŠæå®ããããšã«ããŸãããJobParameter
ïŒãŸãã¯JobParameters
ïŒã䜿ãã«ã¯ã
Beanã@StepScopde
ã§ã¹ã³ãŒãå®çŸ©ãããŠããå¿
èŠããããŸãã
public CsvFileItemReader csvFileItemReader(@Value("#{jobParameters['filePath']}") String filePath) { Resource fileResource = new FileSystemResource(filePath);
Stateãšããã®ã¯ãã³ããããããåãŸã§ã«ã©ããŸã§èªã¿åã£ããïŒåŠçãããïŒãä¿åãããã®ã§ãåèµ·åæã«ç¶ãããå§ãããã
ä»æãã«ãªããã®ã§ãããä»åã¯ãããã£ãèæ
®ã¯ããªãããšã«ããã®ã§ãfalse
ã«ããŠãããŸãã
itemReader.setSaveState(false);
ItemReaders and ItemWriters / Preventing State Persistence
ããšã¯JobãšStepã®å®çŸ©ã
@Bean public Job fileLoadToDatabaseJob() { return jobBuilderFactory .get("fileLoadToDatabaseJob") .incrementer(new RunIdIncrementer()) .start(fileLoadToDatabaseStep()) .build(); } @Bean public Step fileLoadToDatabaseStep() { return stepBuilderFactory .get("fileLoadToDatabaseStep") .<Book, Book>chunk(3) .reader(csvFileItemReader(null)) .processor(loggingBookProcessor()) .writer(bookJpaItemWriter()) .build(); }
èªã¿èŸŒããã¡ã€ã«å ã®ããŒã¿ã10件ãããªãã®ã§ããã£ã³ã¯ãµã€ãºã¯3ã«ããŠããŸãã
JobBuilderFactory#get
ãStepBuilderFactory#get
ã§æå®ããŠããååãJobåãStepåã«ãªããããªã®ã§ãããBeanåã¯å¥ã«ãªãã®ã§
ä»ãšè¡çªããªãããã«Beanå®çŸ©ã®ã¡ãœããåãåããããªã@Bean
ã¢ãããŒã·ã§ã³ã§æå®ãããªãããæ¹ãããã§ãããã
ãŸããincrementer
ã§æå®ããŠããRunIdIncrementer
ã§ãããããã¯JobParameter
ãšããŠrun.id
ãè¿œå ãããã®ã§ãã
RunIdIncrementer (Spring Batch 4.3.5 API)
run.id
ã¯èªåã§ã€ã³ã¯ãªã¡ã³ããããŠããã®ã§ãããSpring Batchã®Jobã¯åããã©ã¡ãŒã¿ãŒæå®ã§ã¯èµ·åã§ããªããªãã®ã§ã
ãã¡ããè¿œå ããŠãããŸãã
ã§ã¯ãããã§1床åäœç¢ºèªããŠãããŸãã
ããã±ãŒãžã³ã°ã
$ mvn package
èµ·åã
$ java -Dspring.batch.job.names=fileLoadToDatabaseJob -jar target/batch-example-0.0.1-SNAPSHOT.jar filePath=src/main/resources/book.csv
Spring Batchã§ã¯ãããã©ã«ãã§ãã¹ãŠã®Jobãèµ·åããããšããŸããããã¯ãspring.batch.job.names
ããããã£ã§èµ·åããJobã
ææã§ããŸãïŒè€æ°ã®å Žåã¯ã«ã³ãåºåãïŒã
ãã®æç¹ã§ã¯ã²ãšã€ããJobããªãã®ã§ãããæåããæå®ããŠãããŸãããã
ãã°ã¯ããããªæãã«åºåãããŸãã
2022-04-24 20:32:03.650 INFO 36238 --- [ main] o.s.b.a.b.JobLauncherApplicationRunner : Running default command line with: [filePath=src/main/resources/book.csv] 2022-04-24 20:32:03.794 INFO 36238 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [SimpleJob: [name=fileLoadToDatabaseJob]] launched with the following parameters: [{run.id=1, filePath=src/main/resources/book.csv}] 2022-04-24 20:32:03.885 INFO 36238 --- [ main] o.s.batch.core.job.SimpleStepHandler : Executing step: [fileLoadToDatabaseStep] 2022-04-24 20:32:04.006 INFO 36238 --- [ main] o.l.s.batch.chunk.CsvFileItemReader : [reader] read book: isbn = 978-4798142470, title = Spring培åºå ¥é Spring Frameworkã«ããJavaã¢ããªã±ãŒã·ã§ã³éçº 2022-04-24 20:32:04.009 INFO 36238 --- [ main] o.l.s.batch.chunk.CsvFileItemReader : [reader] read book: isbn = 978-4774182179, title = [æ¹èšæ°ç]Springå ¥é ââJava ãã¬ãŒã ã¯ãŒã¯ã»ããè¯ãèšèšãšã¢ãŒããã¯ã㣠2022-04-24 20:32:04.009 INFO 36238 --- [ main] o.l.s.batch.chunk.CsvFileItemReader : [reader] read book: isbn = 978-1492076988, title = Spring Boot: Up and Running: Building Cloud Native Java and Kotlin Applications 2022-04-24 20:32:04.014 INFO 36238 --- [ main] o.l.s.batch.chunk.LoggingBookProcessor : [processor] process book: isbn = 978-4798142470, title = Spring培åºå ¥é Spring Frameworkã«ããJavaã¢ããªã±ãŒã·ã§ã³éçº 2022-04-24 20:32:04.014 INFO 36238 --- [ main] o.l.s.batch.chunk.LoggingBookProcessor : [processor] process book: isbn = 978-4774182179, title = [æ¹èšæ°ç]Springå ¥é ââJavaãã¬ãŒã ã¯ãŒã¯ã»ããè¯ãèšèšãšã¢ãŒããã¯ã㣠2022-04-24 20:32:04.014 INFO 36238 --- [ main] o.l.s.batch.chunk.LoggingBookProcessor : [processor] process book: isbn = 978-1492076988, title = Spring Boot: Up and Running: Building Cloud Native Java and Kotlin Applications 2022-04-24 20:32:04.015 INFO 36238 --- [ main] o.l.s.batch.chunk.BookJpaItemWriter : [writer] write items: size = 3 2022-04-24 20:32:04.016 INFO 36238 --- [ main] o.l.s.batch.chunk.BookJpaItemWriter : [writer] write item: isbn = 978-4798142470, title = Spring培åºå ¥é Spring Frameworkã«ããJavaã¢ããªã±ãŒã·ã§ã³éçº 2022-04-24 20:32:04.064 INFO 36238 --- [ main] o.l.s.batch.chunk.BookJpaItemWriter : [writer] write item: isbn = 978-4774182179, title = [æ¹èšæ°ç]Springå ¥é ââJava ãã¬ãŒã ã¯ãŒã¯ã»ããè¯ãèšèšãšã¢ãŒããã¯ã㣠2022-04-24 20:32:04.066 INFO 36238 --- [ main] o.l.s.batch.chunk.BookJpaItemWriter : [writer] write item: isbn = 978-1492076988, title = Spring Boot: Up and Running: Building Cloud Native Java and Kotlin Applications 2022-04-24 20:32:04.111 INFO 36238 --- [ main] o.l.s.batch.chunk.CsvFileItemReader : [reader] read book: isbn = 978-1484237236, title = The Definitive Guide to Spring Batch: Modern Finite Batch Processing in the Cloud 2022-04-24 20:32:04.111 INFO 36238 --- [ main] o.l.s.batch.chunk.CsvFileItemReader : [reader] read book: isbn = 978-4798161488, title = MySQL培åºå ¥é 第4ç MySQL 8.0å¯Ÿå¿ 2022-04-24 20:32:04.111 INFO 36238 --- [ main] o.l.s.batch.chunk.CsvFileItemReader : [reader] read book: isbn = 978-4797393118, title = åºç€ããã®MySQL 第3ç (åºç€ ããã·ãªãŒãº) 2022-04-24 20:32:04.112 INFO 36238 --- [ main] o.l.s.batch.chunk.LoggingBookProcessor : [processor] process book: isbn = 978-1484237236, title = The Definitive Guide to Spring Batch: Modern Finite Batch Processing in the Cloud 2022-04-24 20:32:04.112 INFO 36238 --- [ main] o.l.s.batch.chunk.LoggingBookProcessor : [processor] process book: isbn = 978-4798161488, title = MySQL培åºå ¥é 第4ç MySQL 8.0å¯Ÿå¿ 2022-04-24 20:32:04.112 INFO 36238 --- [ main] o.l.s.batch.chunk.LoggingBookProcessor : [processor] process book: isbn = 978-4797393118, title = åºç€ããã®MySQL 第3ç (åºç€ããã·ãªãŒãº) 2022-04-24 20:32:04.112 INFO 36238 --- [ main] o.l.s.batch.chunk.BookJpaItemWriter : [writer] write items: size = 3 2022-04-24 20:32:04.112 INFO 36238 --- [ main] o.l.s.batch.chunk.BookJpaItemWriter : [writer] write item: isbn = 978-1484237236, title = The Definitive Guide to Spring Batch: Modern Finite Batch Processing in the Cloud 2022-04-24 20:32:04.114 INFO 36238 --- [ main] o.l.s.batch.chunk.BookJpaItemWriter : [writer] write item: isbn = 978-4798161488, title = MySQL培åºå ¥é 第4ç MySQL 8.0å¯Ÿå¿ 2022-04-24 20:32:04.116 INFO 36238 --- [ main] o.l.s.batch.chunk.BookJpaItemWriter : [writer] write item: isbn = 978-4797393118, title = åºç€ããã®MySQL 第3ç (åºç€ ããã·ãªãŒãº) 2022-04-24 20:32:04.145 INFO 36238 --- [ main] o.l.s.batch.chunk.CsvFileItemReader : [reader] read book: isbn = 978-4873116389, title = å®è·µãã€ããã©ãŒãã³ã¹MySQL 第3ç 2022-04-24 20:32:04.145 INFO 36238 --- [ main] o.l.s.batch.chunk.CsvFileItemReader : [reader] read book: isbn = 978-4295000198, title = ããããåŠã¹ãMySQLéçšã»ç®¡ çå ¥éã5.7察å¿ã 2022-04-24 20:32:04.146 INFO 36238 --- [ main] o.l.s.batch.chunk.CsvFileItemReader : [reader] read book: isbn = 978-4798147406, title = 詳解MySQL 5.7 æ¢ãŸãã¬é²åã«ä¹ãé ããªãããã®ãã¯ãã«ã«ã¬ã€ã (NEXT ONE) 2022-04-24 20:32:04.146 INFO 36238 --- [ main] o.l.s.batch.chunk.LoggingBookProcessor : [processor] process book: isbn = 978-4873116389, title = å®è·µãã€ããã©ãŒãã³ã¹MySQL 第3ç 2022-04-24 20:32:04.146 INFO 36238 --- [ main] o.l.s.batch.chunk.LoggingBookProcessor : [processor] process book: isbn = 978-4295000198, title = ããããåŠã¹ãMySQLéçšã»ç®¡çå ¥éã5.7察å¿ã 2022-04-24 20:32:04.146 INFO 36238 --- [ main] o.l.s.batch.chunk.LoggingBookProcessor : [processor] process book: isbn = 978-4798147406, title = 詳解MySQL 5.7 æ¢ãŸã㬠é²åã«ä¹ãé ããªãããã®ãã¯ãã«ã«ã¬ã€ã (NEXT ONE) 2022-04-24 20:32:04.147 INFO 36238 --- [ main] o.l.s.batch.chunk.BookJpaItemWriter : [writer] write items: size = 3 2022-04-24 20:32:04.147 INFO 36238 --- [ main] o.l.s.batch.chunk.BookJpaItemWriter : [writer] write item: isbn = 978-4873116389, title = å®è·µãã€ããã©ãŒãã³ã¹MySQL 第3ç 2022-04-24 20:32:04.149 INFO 36238 --- [ main] o.l.s.batch.chunk.BookJpaItemWriter : [writer] write item: isbn = 978-4295000198, title = ããããåŠã¹ãMySQLéçšã»ç®¡ çå ¥éã5.7察å¿ã 2022-04-24 20:32:04.150 INFO 36238 --- [ main] o.l.s.batch.chunk.BookJpaItemWriter : [writer] write item: isbn = 978-4798147406, title = 詳解MySQL 5.7 æ¢ãŸãã¬é²åã«ä¹ãé ããªãããã®ãã¯ãã«ã«ã¬ã€ã (NEXT ONE) 2022-04-24 20:32:04.189 INFO 36238 --- [ main] o.l.s.batch.chunk.CsvFileItemReader : [reader] read book: isbn = 978-4774170206, title = MariaDB&MySQLå šæ©èœãã€ãã« 2022-04-24 20:32:04.189 INFO 36238 --- [ main] o.l.s.batch.chunk.CsvFileItemReader : [reader] readed books 2022-04-24 20:32:04.189 INFO 36238 --- [ main] o.l.s.batch.chunk.LoggingBookProcessor : [processor] process book: isbn = 978-4774170206, title = MariaDB&MySQLå šæ©èœãã€ãã« 2022-04-24 20:32:04.189 INFO 36238 --- [ main] o.l.s.batch.chunk.BookJpaItemWriter : [writer] write items: size = 1 2022-04-24 20:32:04.190 INFO 36238 --- [ main] o.l.s.batch.chunk.BookJpaItemWriter : [writer] write item: isbn = 978-4774170206, title = MariaDB&MySQLå šæ©èœãã€ãã« 2022-04-24 20:32:04.251 INFO 36238 --- [ main] o.s.batch.core.step.AbstractStep : Step: [fileLoadToDatabaseStep] executed in 365ms 2022-04-24 20:32:04.311 INFO 36238 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [SimpleJob: [name=fileLoadToDatabaseJob]] completed with the following parameters: [{run.id=1, filePath=src/main/resources/book.csv}] and the following status: [COMPLETED] in 464ms
ItemReader
ïŒãã£ã³ã¯ãµã€ãºåç¹°ãè¿ãïŒ â ItemProcessor
ïŒãã£ã³ã¯ãµã€ãºåç¹°ãè¿ãïŒ â ItemWriter
ïŒãã£ã³ã¯ãµã€ãºã®ããŒã¿ãäžæ°ã«
åŒãæž¡ãïŒãååŸãããã£ã³ã¯ã®æ°ã ãç¹°ãè¿ããšããæåã«ãªã£ãŠããŸãã
ãã®ãããã®åŒã³åºãã¯ã以äžãèŠããšè¯ãããã§ãã
run.id
ãæå®ãããŠããŸããã
2022-04-24 20:32:03.794 INFO 36238 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [SimpleJob: [name=fileLoadToDatabaseJob]] launched with the following parameters: [{run.id=1, filePath=src/main/resources/book.csv}]
ããŒã¿ããŒã¹ã®æ¹ã¯ãJobãèµ·åãããŸã§ã¯ãªã«ãããŒãã«ããããŸããã
mysql> use practice; Database changed mysql> show tables; Empty set (0.00 sec)
Jobå®è¡åŸã¯ä»¥äžã®ããã«ãªã£ãŠããŸãã
mysql> show tables; +------------------------------+ | Tables_in_practice | +------------------------------+ | BATCH_JOB_EXECUTION | | BATCH_JOB_EXECUTION_CONTEXT | | BATCH_JOB_EXECUTION_PARAMS | | BATCH_JOB_EXECUTION_SEQ | | BATCH_JOB_INSTANCE | | BATCH_JOB_SEQ | | BATCH_STEP_EXECUTION | | BATCH_STEP_EXECUTION_CONTEXT | | BATCH_STEP_EXECUTION_SEQ | | book | +------------------------------+ 10 rows in set (0.00 sec)
ããŒã¿ãå ¥ã£ãŠããããšã®ç¢ºèªã
mysql> select * from book; +----------------+---------------------------------------------------------------------------------------------------------+-------+--------------+ | isbn | title | price | publish_date | +----------------+---------------------------------------------------------------------------------------------------------+-------+--------------+ | 978-1484237236 | The Definitive Guide to Spring Batch: Modern Finite Batch Processing in the Cloud | 7361 | 2019-07-09 | | 978-1492076988 | Spring Boot: Up and Running: Building Cloud Native Java and Kotlin Applications | 6265 | 2021-03-23 | | 978-4295000198 | ããããåŠã¹ãMySQLéçšã»ç®¡çå ¥éã5.7察å¿ã | 2860 | 2016-12-15 | | 978-4774170206 | MariaDB&MySQLå šæ©èœãã€ãã« | 3850 | 2014-12-18 | | 978-4774182179 | [æ¹èšæ°ç]Springå ¥é ââJavaãã¬ãŒã ã¯ãŒã¯ã»ããè¯ãèšèšãšã¢ãŒããã¯ã㣠| 4180 | 2016-06-14 | | 978-4797393118 | åºç€ããã®MySQL 第3ç (åºç€ããã·ãªãŒãº) | 6038 | 2017-09-22 | | 978-4798142470 | Spring培åºå ¥é Spring Frameworkã«ããJavaã¢ããªã±ãŒã·ã§ã³éçº | 4400 | 2016-07-21 | | 978-4798147406 | 詳解MySQL 5.7 æ¢ãŸãã¬é²åã«ä¹ãé ããªãããã®ãã¯ãã«ã«ã¬ã€ã (NEXT ONE) | 3960 | 2016-08-26 | | 978-4798161488 | MySQL培åºå ¥é 第4ç MySQL 8.0å¯Ÿå¿ | 4180 | 2020-07-06 | | 978-4873116389 | å®è·µãã€ããã©ãŒãã³ã¹MySQL 第3ç | 5280 | 2013-11-25 | +----------------+---------------------------------------------------------------------------------------------------------+-------+--------------+ 10 rows in set (0.01 sec)
ä»ã®ããŒãã«ã®å 容ã¯ããããªæãã«ãªã£ãŠããŸãã
mysql> select * from BATCH_JOB_EXECUTION; +------------------+---------+-----------------+----------------------------+----------------------------+----------------------------+-----------+-----------+--------------+----------------------------+----------------------------+ | JOB_EXECUTION_ID | VERSION | JOB_INSTANCE_ID | CREATE_TIME | START_TIME | END_TIME | STATUS | EXIT_CODE | EXIT_MESSAGE | LAST_UPDATED | JOB_CONFIGURATION_LOCATION | +------------------+---------+-----------------+----------------------------+----------------------------+----------------------------+-----------+-----------+--------------+----------------------------+----------------------------+ | 1 | 2 | 1 | 2022-04-24 20:32:03.720000 | 2022-04-24 20:32:03.814000 | 2022-04-24 20:32:04.278000 | COMPLETED | COMPLETED | | 2022-04-24 20:32:04.279000 | NULL | +------------------+---------+-----------------+----------------------------+----------------------------+----------------------------+-----------+-----------+--------------+----------------------------+----------------------------+ 1 row in set (0.00 sec) mysql> select * from BATCH_JOB_EXECUTION_CONTEXT; +------------------+--------------------------------+--------------------+ | JOB_EXECUTION_ID | SHORT_CONTEXT | SERIALIZED_CONTEXT | +------------------+--------------------------------+--------------------+ | 1 | {"@class":"java.util.HashMap"} | NULL | +------------------+--------------------------------+--------------------+ 1 row in set (0.00 sec) mysql> select * from BATCH_JOB_EXECUTION_PARAMS; +------------------+---------+----------+-----------------------------+----------------------------+----------+------------+-------------+ | JOB_EXECUTION_ID | TYPE_CD | KEY_NAME | STRING_VAL | DATE_VAL | LONG_VAL | DOUBLE_VAL | IDENTIFYING | +------------------+---------+----------+-----------------------------+----------------------------+----------+------------+-------------+ | 1 | LONG | run.id | | 1970-01-01 09:00:00.000000 | 1 | 0 | Y | | 1 | STRING | filePath | src/main/resources/book.csv | 1970-01-01 09:00:00.000000 | 0 | 0 | Y | +------------------+---------+----------+-----------------------------+----------------------------+----------+------------+-------------+ 2 rows in set (0.00 sec) mysql> select * from BATCH_JOB_EXECUTION_SEQ; +----+------------+ | ID | UNIQUE_KEY | +----+------------+ | 1 | 0 | +----+------------+ 1 row in set (0.00 sec) mysql> select * from BATCH_JOB_INSTANCE; +-----------------+---------+-----------------------+----------------------------------+ | JOB_INSTANCE_ID | VERSION | JOB_NAME | JOB_KEY | +-----------------+---------+-----------------------+----------------------------------+ | 1 | 0 | fileLoadToDatabaseJob | 2247a3263300ca04598c73ac33b0fb7e | +-----------------+---------+-----------------------+----------------------------------+ 1 row in set (0.00 sec) mysql> select * from BATCH_JOB_SEQ; +----+------------+ | ID | UNIQUE_KEY | +----+------------+ | 1 | 0 | +----+------------+ 1 row in set (0.00 sec) mysql> select * from BATCH_STEP_EXECUTION; +-------------------+---------+------------------------+------------------+----------------------------+----------------------------+-----------+--------------+------------+--------------+-------------+-----------------+------------------+--------------------+----------------+-----------+--------------+----------------------------+ | STEP_EXECUTION_ID | VERSION | STEP_NAME | JOB_EXECUTION_ID | START_TIME | END_TIME | STATUS | COMMIT_COUNT | READ_COUNT | FILTER_COUNT | WRITE_COUNT | READ_SKIP_COUNT | WRITE_SKIP_COUNT | PROCESS_SKIP_COUNT | ROLLBACK_COUNT | EXIT_CODE | EXIT_MESSAGE | LAST_UPDATED | +-------------------+---------+------------------------+------------------+----------------------------+----------------------------+-----------+--------------+------------+--------------+-------------+-----------------+------------------+--------------------+----------------+-----------+--------------+----------------------------+ | 1 | 6 | fileLoadToDatabaseStep | 1 | 2022-04-24 20:32:03.885000 | 2022-04-24 20:32:04.250000 | COMPLETED | 4 | 10 | 0 | 10 | 0 | 0 | 0 | 0 | COMPLETED | | 2022-04-24 20:32:04.252000 | +-------------------+---------+------------------------+------------------+----------------------------+----------------------------+-----------+--------------+------------+--------------+-------------+-----------------+------------------+--------------------+----------------+-----------+--------------+----------------------------+ 1 row in set (0.00 sec) mysql> select * from BATCH_STEP_EXECUTION_CONTEXT; +-------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------+ | STEP_EXECUTION_ID | SHORT_CONTEXT | SERIALIZED_CONTEXT | +-------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------+ | 1 | {"@class":"java.util.HashMap","batch.taskletType":"org.springframework.batch.core.step.item.ChunkOrientedTasklet","batch.stepType":"org.springframework.batch.core.step.tasklet.TaskletStep"} | NULL | +-------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------+ 1 row in set (0.00 sec) mysql> select * from BATCH_STEP_EXECUTION_SEQ; +----+------------+ | ID | UNIQUE_KEY | +----+------------+ | 1 | 0 | +----+------------+ 1 row in set (0.01 sec)
RunIdIncrementer
ã䜿çšããŠããã®ã§ãåãèµ·åãã©ã¡ãŒã¿ãŒã§ãã1床Jobãèµ·åã§ããŸãã
$ java -Dspring.batch.job.names=fileLoadToDatabaseJob -jar target/batch-example-0.0.1-SNAPSHOT.jar filePath=src/main/resources/book.csv
ãã®æãrun.id
ã¯2ã«ãªã£ãŠããŸãã
2022-04-24 20:33:56.256 INFO 36352 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [SimpleJob: [name=fileLoadToDatabaseJob]] launched with the following parameters: [{run.id=2, filePath=src/main/resources/book.csv}]
ãããRunIdIncrementer
ãåé€ããŠ
@Bean public Job fileLoadToDatabaseJob() { return jobBuilderFactory .get("fileLoadToDatabaseJob") // .incrementer(new RunIdIncrementer()) .start(fileLoadToDatabaseStep()) .build(); }
åãJobParameter
å®çŸ©ã§èµ·åããããšãããšããã§ã«å®äºæžã¿ãšããããšã§ãšã©ãŒã«ãªããŸãã
Caused by: org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException: A job instance already exists and is complete for parameters={filePath=src/main/resources/book.csv}. If you want to run this job again, change the parameters.
ä»åã¯ãã¡ãã®å®çŸ©ã§ã¯ãªãã§ãããJobParameter
ããããã䜿ã£ãŠããªãå Žåã¯ãå®äºããJob
ã¯ä»¥äžã®æ§ã«ç©ºæ¯ãããŸãã
2022-04-24 21:09:56.925 INFO 38225 --- [ main] o.s.batch.core.job.SimpleStepHandler : Step already complete or not restartable, so no action to execute: StepExecution: id=8, version=6, name=fileLoadToDatabaseStep, status=COMPLETED, exitStatus=COMPLETED, readCount=10, filterCount=0, writeCount=10 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=4, rollbackCount=0, exitDescription=
Spring BatchãæäŸããItemReaderãItemWriterã䜿ã
å
ã»ã©ã¯ãItemReader
ããã³ItemWriter
ãèªåã§äœæããŸããã
ã§ãããSpring BatchãItemReader
ãšItemWriter
ã®å®è£
ãããã€ãæäŸããŠããã®ã§ããã¡ãã䜿çšããã°èªåã§ItemReader
ãItemWriter
ã
å®è£
ããã«Jobãæ§ç¯ã§ããããããŸãã
List of ItemReaders and ItemWriters
ä»åã§ããã°ãFlatFileItemReader
ãšJpaItemWriter
ã䜿ããŸããã
ItemReaders and ItemWriters / Flat Files
FlatFileItemReader (Spring Batch 4.3.5 API)
JpaItemWriter (Spring Batch 4.3.5 API)
Job
ããã³Step
ã®å®çŸ©ã¯ãã¡ãã
src/main/java/org/littlewings/spring/batch/config/FileLoadToDatabaseSimplyJobConfig.java
package org.littlewings.spring.batch.config; import java.time.format.DateTimeFormatter; import javax.persistence.EntityManagerFactory; import org.littlewings.spring.batch.chunk.LoggingBookProcessor; import org.littlewings.spring.batch.entity.Book; import org.springframework.batch.core.Job; import org.springframework.batch.core.Step; import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; import org.springframework.batch.core.configuration.annotation.StepScope; import org.springframework.batch.core.launch.support.RunIdIncrementer; import org.springframework.batch.item.database.JpaItemWriter; import org.springframework.batch.item.database.builder.JpaItemWriterBuilder; import org.springframework.batch.item.file.FlatFileItemReader; import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder; import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource; import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar; import org.springframework.format.support.DefaultFormattingConversionService; @Configuration public class FileLoadToDatabaseSimplyJobConfig { @Autowired JobBuilderFactory jobBuilderFactory; @Autowired StepBuilderFactory stepBuilderFactory; @Autowired EntityManagerFactory entityManagerFactory; @Bean public Job fileLoadToDatabaseSimplyJob() { return jobBuilderFactory .get("fileLoadToDatabaseSimplyJob") .incrementer(new RunIdIncrementer()) .start(fileLoadToDatabaseSimplyStep()) .build(); } @Bean public Step fileLoadToDatabaseSimplyStep() { return stepBuilderFactory .get("fileLoadToDatabaseSimplyStep") .<Book, Book>chunk(3) .reader(flatFileBookItemReader(null, false)) .processor(simpleLoggingBookProcessor()) .writer(jpaBookItemWriter()) .build(); } @StepScope @Bean public FlatFileItemReader<Book> flatFileBookItemReader( @Value("#{jobParameters['filePath']}") String filePath, @Value("#{jobParameters['hasHeader'] ?: true}") boolean hasHeader ) { Resource fileResource = new FileSystemResource(filePath); DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService(false); DateTimeFormatterRegistrar dateTimeFormatterRegistrar = new DateTimeFormatterRegistrar(); dateTimeFormatterRegistrar.setDateFormatter(DateTimeFormatter.ofPattern("uuuu-MM-dd")); dateTimeFormatterRegistrar.registerFormatters(conversionService); BeanWrapperFieldSetMapper<Book> fieldSetMapper = new BeanWrapperFieldSetMapper<>(); fieldSetMapper.setConversionService(conversionService); fieldSetMapper.setTargetType(Book.class); try { fieldSetMapper.afterPropertiesSet(); } catch (Exception e) { throw new RuntimeException(e); } return new FlatFileItemReaderBuilder<Book>() .name("flatFileBookItemReader") .resource(fileResource) .encoding("UTF-8") .delimited() .names(new String[]{"isbn", "title", "price", "publishDate"}) .linesToSkip(hasHeader ? 1 : 0) .fieldSetMapper(fieldSetMapper) .saveState(false) .build(); } @StepScope @Bean public LoggingBookProcessor simpleLoggingBookProcessor() { return new LoggingBookProcessor(); } @StepScope @Bean public JpaItemWriter<Book> jpaBookItemWriter() { return new JpaItemWriterBuilder<Book>() .entityManagerFactory(entityManagerFactory) .build(); } }
ItemProcessor
ã®æ¹ã¯ãå
ã»ã©ã®ãã®ããã®ãŸãŸäœ¿ã£ãŠããŸãã
FlatFileItemReader
ã®æ§ç¯ã¯ãã¡ãã
@StepScope @Bean public FlatFileItemReader<Book> flatFileBookItemReader( @Value("#{jobParameters['filePath']}") String filePath, @Value("#{jobParameters['hasHeader'] ?: true}") boolean hasHeader ) { Resource fileResource = new FileSystemResource(filePath); DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService(false); DateTimeFormatterRegistrar dateTimeFormatterRegistrar = new DateTimeFormatterRegistrar(); dateTimeFormatterRegistrar.setDateFormatter(DateTimeFormatter.ofPattern("uuuu-MM-dd")); dateTimeFormatterRegistrar.registerFormatters(conversionService); BeanWrapperFieldSetMapper<Book> fieldSetMapper = new BeanWrapperFieldSetMapper<>(); fieldSetMapper.setConversionService(conversionService); fieldSetMapper.setTargetType(Book.class); try { fieldSetMapper.afterPropertiesSet(); } catch (Exception e) { throw new RuntimeException(e); } return new FlatFileItemReaderBuilder<Book>() .name("flatFileBookItemReader") .resource(fileResource) .encoding("UTF-8") .delimited() .names(new String[]{"isbn", "title", "price", "publishDate"}) .linesToSkip(hasHeader ? 1 : 0) .fieldSetMapper(fieldSetMapper) .saveState(false) .build(); }
FlatFileItemReader
ã¯ãFlatFileItemReaderBuilder
ã§æ§ç¯ããŸãã
return new FlatFileItemReaderBuilder<Book>() .name("flatFileBookItemReader") .resource(fileResource) .encoding("UTF-8") .delimited() .names(new String[]{"isbn", "title", "price", "publishDate"}) .linesToSkip(hasHeader ? 1 : 0) .fieldSetMapper(fieldSetMapper) .saveState(false) .build();
names
ã§åé
ç®ã®ååãå®çŸ©ããŠãããBeanWrapperFieldSetMapper
ã§Book
ã«ãããã³ã°ããŸããBook
ã®ããããã£ã«LocalDate
ã
䜿çšãããã®ãããã®ã§ãDefaultFormattingConversionService
ãšDateTimeFormatterRegistrar
ã䜿ã£ãŠæ¥ä»ãããŒã¹ã§ããããã«
ããŠããŸãã
DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService(false); DateTimeFormatterRegistrar dateTimeFormatterRegistrar = new DateTimeFormatterRegistrar(); dateTimeFormatterRegistrar.setDateFormatter(DateTimeFormatter.ofPattern("uuuu-MM-dd")); dateTimeFormatterRegistrar.registerFormatters(conversionService); BeanWrapperFieldSetMapper<Book> fieldSetMapper = new BeanWrapperFieldSetMapper<>(); fieldSetMapper.setConversionService(conversionService); fieldSetMapper.setTargetType(Book.class);
èªã¿èŸŒãCSVãã¡ã€ã«ã®ããããŒã®æç¡ã¯ãJobParameter
ã§æå®ã§ããããã«ããŸããã
public FlatFileItemReader<Book> flatFileBookItemReader( @Value("#{jobParameters['filePath']}") String filePath, @Value("#{jobParameters['hasHeader'] ?: true}") boolean hasHeader ) {
ããã©ã«ãã§ããããŒæãã«ããŠããŸãã
JpaItemWriter
ã¯ãJpaItemWriterBuilder
ã§æ§ç¯ããŸãããã®æãEntityManagerFactory
ãå¿
èŠã«ãªããŸãã
@StepScope @Bean public JpaItemWriter<Book> jpaBookItemWriter() { return new JpaItemWriterBuilder<Book>() .entityManagerFactory(entityManagerFactory) .build(); }
ã¢ããªã±ãŒã·ã§ã³ãã§ããã®ã§ãå®è¡ããŠã¿ãŸãããã
æåã«ãããŒã¿ãåé€ããŠãããŸãã
mysql> truncate table book; Query OK, 0 rows affected (0.34 sec) mysql> select * from book; Empty set (0.00 sec)
ããã±ãŒãžã³ã°ããŠ
$ mvn package
å®è¡ããŠã¿ãŸããå
ã»ã©ãšã¯spring.batch.job.names
ã«æå®ããJobåãå€æŽããŸãã
$ java -Dspring.batch.job.names=fileLoadToDatabaseSimplyJob -jar target/batch-example-0.0.1-SNAPSHOT.jar filePath=src/main/resources/book_with_header.csv
ãã°ã
2022-04-24 20:48:35.470 INFO 37031 --- [ main] o.s.b.a.b.JobLauncherApplicationRunner : Running default command line with: [filePath=src/main/resources/book_with_header.csv] 2022-04-24 20:48:35.682 INFO 37031 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [SimpleJob: [name=fileLoadToDatabaseSimplyJob]] launched with the following parameters: [{run.id=1, filePath=src/main/resources/book_with_header.csv}] 2022-04-24 20:48:35.817 INFO 37031 --- [ main] o.s.batch.core.job.SimpleStepHandler : Executing step: [fileLoadToDatabaseSimplyStep] 2022-04-24 20:48:35.981 INFO 37031 --- [ main] o.l.s.batch.chunk.LoggingBookProcessor : [processor] process book: isbn = 978-4798142470, title = Spring培åºå ¥é Spring Frameworkã«ããJavaã¢ããªã±ãŒã·ã§ã³éçº 2022-04-24 20:48:35.982 INFO 37031 --- [ main] o.l.s.batch.chunk.LoggingBookProcessor : [processor] process book: isbn = 978-4774182179, title = [æ¹èšæ°ç]Springå ¥é ââJavaãã¬ãŒã ã¯ãŒã¯ã»ããè¯ãèšèšãšã¢ãŒããã¯ã㣠2022-04-24 20:48:35.982 INFO 37031 --- [ main] o.l.s.batch.chunk.LoggingBookProcessor : [processor] process book: isbn = 978-1492076988, title = Spring Boot: Up and Running: Building Cloud Native Java and Kotlin Applications 2022-04-24 20:48:36.078 INFO 37031 --- [ main] o.l.s.batch.chunk.LoggingBookProcessor : [processor] process book: isbn = 978-1484237236, title = The Definitive Guide to Spring Batch: Modern Finite Batch Processing in the Cloud 2022-04-24 20:48:36.078 INFO 37031 --- [ main] o.l.s.batch.chunk.LoggingBookProcessor : [processor] process book: isbn = 978-4798161488, title = MySQL培åºå ¥é 第4ç MySQL 8.0å¯Ÿå¿ 2022-04-24 20:48:36.078 INFO 37031 --- [ main] o.l.s.batch.chunk.LoggingBookProcessor : [processor] process book: isbn = 978-4797393118, title = åºç€ããã®MySQL 第3ç (åºç€ããã·ãªãŒãº) 2022-04-24 20:48:36.118 INFO 37031 --- [ main] o.l.s.batch.chunk.LoggingBookProcessor : [processor] process book: isbn = 978-4873116389, title = å®è·µãã€ããã©ãŒãã³ã¹MySQL 第3ç 2022-04-24 20:48:36.118 INFO 37031 --- [ main] o.l.s.batch.chunk.LoggingBookProcessor : [processor] process book: isbn = 978-4295000198, title = ããããåŠã¹ãMySQLéçšã»ç®¡çå ¥éã5.7察å¿ã 2022-04-24 20:48:36.118 INFO 37031 --- [ main] o.l.s.batch.chunk.LoggingBookProcessor : [processor] process book: isbn = 978-4798147406, title = 詳解MySQL 5.7 æ¢ãŸã㬠é²åã«ä¹ãé ããªãããã®ãã¯ãã«ã«ã¬ã€ã (NEXT ONE) 2022-04-24 20:48:36.160 INFO 37031 --- [ main] o.l.s.batch.chunk.LoggingBookProcessor : [processor] process book: isbn = 978-4774170206, title = MariaDB&MySQLå šæ©èœãã€ãã« 2022-04-24 20:48:36.208 INFO 37031 --- [ main] o.s.batch.core.step.AbstractStep : Step: [fileLoadToDatabaseSimplyStep] executed in 391ms 2022-04-24 20:48:36.298 INFO 37031 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [SimpleJob: [name=fileLoadToDatabaseSimplyJob]] completed with the following parameters: [{run.id=1, filePath=src/main/resources/book_with_header.csv}] and the following status: [COMPLETED] in 514ms
ããŒã¿ãå ¥ããŸããã
mysql> select * from book; +----------------+---------------------------------------------------------------------------------------------------------+-------+--------------+ | isbn | title | price | publish_date | +----------------+---------------------------------------------------------------------------------------------------------+-------+--------------+ | 978-1484237236 | The Definitive Guide to Spring Batch: Modern Finite Batch Processing in the Cloud | 7361 | 2019-07-09 | | 978-1492076988 | Spring Boot: Up and Running: Building Cloud Native Java and Kotlin Applications | 6265 | 2021-03-23 | | 978-4295000198 | ããããåŠã¹ãMySQLéçšã»ç®¡çå ¥éã5.7察å¿ã | 2860 | 2016-12-15 | | 978-4774170206 | MariaDB&MySQLå šæ©èœãã€ãã« | 3850 | 2014-12-18 | | 978-4774182179 | [æ¹èšæ°ç]Springå ¥é ââJavaãã¬ãŒã ã¯ãŒã¯ã»ããè¯ãèšèšãšã¢ãŒããã¯ã㣠| 4180 | 2016-06-14 | | 978-4797393118 | åºç€ããã®MySQL 第3ç (åºç€ããã·ãªãŒãº) | 6038 | 2017-09-22 | | 978-4798142470 | Spring培åºå ¥é Spring Frameworkã«ããJavaã¢ããªã±ãŒã·ã§ã³éçº | 4400 | 2016-07-21 | | 978-4798147406 | 詳解MySQL 5.7 æ¢ãŸãã¬é²åã«ä¹ãé ããªãããã®ãã¯ãã«ã«ã¬ã€ã (NEXT ONE) | 3960 | 2016-08-26 | | 978-4798161488 | MySQL培åºå ¥é 第4ç MySQL 8.0å¯Ÿå¿ | 4180 | 2020-07-06 | | 978-4873116389 | å®è·µãã€ããã©ãŒãã³ã¹MySQL 第3ç | 5280 | 2013-11-25 | +----------------+---------------------------------------------------------------------------------------------------------+-------+--------------+ 10 rows in set (0.00 sec)
ä»åã®Job
ã§ããããŒãªãã®ãã¡ã€ã«ãèªãæã¯ãJobParameter
ã§ããhasHeader
ãfalse
ã«ããŸãã
$ java -Dspring.batch.job.names=fileLoadToDatabaseSimplyJob -jar target/batch-example-0.0.1-SNAPSHOT.jar filePath=src/main/resources/book.csv hasHeader=false
Taskletãäœæãã
æåŸã«ãTaskletãäœæããŠã¿ãŸãã
ä»åã¯ããã°åºåã®ã¿ãªã®ã§ãããªæãã§äœæã
src/main/java/org/littlewings/spring/batch/tasklet/LoggingBookTasklet.java
package org.littlewings.spring.batch.tasklet; import java.time.format.DateTimeFormatter; import org.littlewings.spring.batch.repository.BookRepository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.batch.core.StepContribution; import org.springframework.batch.core.scope.context.ChunkContext; import org.springframework.batch.core.step.tasklet.Tasklet; import org.springframework.batch.repeat.RepeatStatus; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Sort; public class LoggingBookTasklet implements Tasklet { Logger logger = LoggerFactory.getLogger(LoggingBookTasklet.class); @Autowired BookRepository bookRepository; @Override public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { DateTimeFormatter publishDateFormatter = DateTimeFormatter.ofPattern("uuuu-MM-dd"); bookRepository .findAll(Sort.by(Sort.Direction.DESC, "price")) .forEach(book -> logger.info( "[tasklet] isbn = {}, title = {}, price = {}, publishDate = {}", book.getIsbn(), book.getTitle(), book.getPrice(), book.getPublishDate().format(publishDateFormatter) )); return RepeatStatus.FINISHED; } }
Job
ããã³Step
å®çŸ©ã
src/main/java/org/littlewings/spring/batch/config/LoggingDatabaseJobConfig.java
package org.littlewings.spring.batch.config; import org.littlewings.spring.batch.tasklet.LoggingBookTasklet; import org.springframework.batch.core.Job; import org.springframework.batch.core.Step; import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; import org.springframework.batch.core.configuration.annotation.StepScope; import org.springframework.batch.core.launch.support.RunIdIncrementer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class LoggingDatabaseJobConfig { @Autowired JobBuilderFactory jobBuilderFactory; @Autowired StepBuilderFactory stepBuilderFactory; @Bean public Job loggingDatabaseJog() { return jobBuilderFactory .get("loggingDatabaseJob") .incrementer(new RunIdIncrementer()) .start(loggingDatabaseStep()) .build(); } @Bean public Step loggingDatabaseStep() { return stepBuilderFactory .get("loggingDatabaseStep") .tasklet(loggingBookTasklet()) .build(); } @StepScope @Bean public LoggingBookTasklet loggingBookTasklet() { return new LoggingBookTasklet(); } }
ç¹åŸŽçãªãšããã¯ãStep
ãæ§ç¯ããéã«tasklet
ãæå®ããŠããããšã§ããã
@Bean public Step loggingDatabaseStep() { return stepBuilderFactory .get("loggingDatabaseStep") .tasklet(loggingBookTasklet()) .build(); }
ããã±ãŒãžã³ã°ããŠ
$ mvn package
å®è¡ã
$ java -Dspring.batch.job.names=loggingDatabaseJob -jar target/batch-example-0.0.1-SNAPSHOT.jar
ãã°ã
2022-04-24 21:00:08.593 INFO 37435 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [SimpleJob: [name=loggingDatabaseJob]] launched with the following parameters: [{run.id=1}] 2022-04-24 21:00:08.697 INFO 37435 --- [ main] o.s.batch.core.job.SimpleStepHandler : Executing step: [loggingDatabaseStep] 2022-04-24 21:00:08.990 INFO 37435 --- [ main] o.l.s.batch.tasklet.LoggingBookTasklet : [tasklet] isbn = 978-1484237236, title = The Definitive Guide to Spring Batch: Modern Finite Batch Processing in the Cloud, price = 7361, publishDate = 2019-07-09 2022-04-24 21:00:08.990 INFO 37435 --- [ main] o.l.s.batch.tasklet.LoggingBookTasklet : [tasklet] isbn = 978-1492076988, title = Spring Boot: Up and Running: Building Cloud Native Java and Kotlin Applications, price = 6265, publishDate = 2021-03-23 2022-04-24 21:00:08.990 INFO 37435 --- [ main] o.l.s.batch.tasklet.LoggingBookTasklet : [tasklet] isbn = 978-4797393118, title = åºç€ããã®MySQL 第3ç (åºç€ããã·ãªãŒãº), price = 6038, publishDate = 2017-09-22 2022-04-24 21:00:08.990 INFO 37435 --- [ main] o.l.s.batch.tasklet.LoggingBookTasklet : [tasklet] isbn = 978-4873116389, title = å®è·µãã€ããã©ãŒãã³ã¹MySQL 第3ç, price = 5280, publishDate = 2013-11-25 2022-04-24 21:00:08.990 INFO 37435 --- [ main] o.l.s.batch.tasklet.LoggingBookTasklet : [tasklet] isbn = 978-4798142470, title = Spring培åºå ¥é Spring Frameworkã«ããJavaã¢ããªã±ãŒã·ã§ã³éçº, price = 4400, publishDate = 2016-07-21 2022-04-24 21:00:08.991 INFO 37435 --- [ main] o.l.s.batch.tasklet.LoggingBookTasklet : [tasklet] isbn = 978-4774182179, title = [æ¹èšæ°ç]Springå ¥é ââJavaãã¬ãŒã ã¯ãŒã¯ã»ããè¯ãèšèšãšã¢ãŒããã¯ãã£, price = 4180, publishDate = 2016-06-14 2022-04-24 21:00:08.991 INFO 37435 --- [ main] o.l.s.batch.tasklet.LoggingBookTasklet : [tasklet] isbn = 978-4798161488, title = MySQL培åºå ¥é 第4ç MySQL 8.0察å¿, price = 4180, publishDate = 2020-07-06 2022-04-24 21:00:08.991 INFO 37435 --- [ main] o.l.s.batch.tasklet.LoggingBookTasklet : [tasklet] isbn = 978-4798147406, title = 詳解MySQL 5.7 æ¢ãŸãã¬é²åã«ä¹ãé ã㪠ãããã®ãã¯ãã«ã«ã¬ã€ã (NEXT ONE), price = 3960, publishDate = 2016-08-26 2022-04-24 21:00:08.991 INFO 37435 --- [ main] o.l.s.batch.tasklet.LoggingBookTasklet : [tasklet] isbn = 978-4774170206, title = MariaDB&MySQLå šæ©èœãã€ãã«, price = 3850, publishDate = 2014-12-18 2022-04-24 21:00:08.991 INFO 37435 --- [ main] o.l.s.batch.tasklet.LoggingBookTasklet : [tasklet] isbn = 978-4295000198, title = ããããåŠã¹ãMySQLéçšã»ç®¡çå ¥éã5.7 察å¿ã, price = 2860, publishDate = 2016-12-15 2022-04-24 21:00:09.041 INFO 37435 --- [ main] o.s.batch.core.step.AbstractStep : Step: [loggingDatabaseStep] executed in 343ms 2022-04-24 21:00:09.101 INFO 37435 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [SimpleJob: [name=loggingDatabaseJob]] completed with the following parameters: [{run.id=1}] and the following status: [COMPLETED] in 454ms
ããã§ãTaskletã®æ¹ãOKã§ããã
JobRepositoryãäœæããSQLã«ã€ããŠ
ä»åãspring.batch.jdbc.initialize-schema
ãalways
ã«ããŠããã®ã§Spring Batchã®JobRepository
ã§äœ¿ãããŒãã«ãèªåã§äœæããŠ
ãããŠããŸãããããã®SQLã¯ä»¥äžã®ãã£ã¬ã¯ããªã«ããããã§ãã
ã¡ãªã¿ã«ããããŸã§å®è¡ããåŸã®åããŒãã«ã®ç¶æ ã¯ããããªæãã«ãªããŸããã
mysql> select * from BATCH_JOB_EXECUTION; +------------------+---------+-----------------+----------------------------+----------------------------+----------------------------+-----------+-----------+--------------+----------------------------+----------------------------+ | JOB_EXECUTION_ID | VERSION | JOB_INSTANCE_ID | CREATE_TIME | START_TIME | END_TIME | STATUS | EXIT_CODE | EXIT_MESSAGE | LAST_UPDATED | JOB_CONFIGURATION_LOCATION | +------------------+---------+-----------------+----------------------------+----------------------------+----------------------------+-----------+-----------+--------------+----------------------------+----------------------------+ | 1 | 2 | 1 | 2022-04-24 20:32:03.720000 | 2022-04-24 20:32:03.814000 | 2022-04-24 20:32:04.278000 | COMPLETED | COMPLETED | | 2022-04-24 20:32:04.279000 | NULL | | 2 | 2 | 2 | 2022-04-24 20:33:56.195000 | 2022-04-24 20:33:56.274000 | 2022-04-24 20:33:56.720000 | COMPLETED | COMPLETED | | 2022-04-24 20:33:56.720000 | NULL | | 3 | 2 | 3 | 2022-04-24 20:48:35.586000 | 2022-04-24 20:48:35.731000 | 2022-04-24 20:48:36.245000 | COMPLETED | COMPLETED | | 2022-04-24 20:48:36.246000 | NULL | | 4 | 2 | 4 | 2022-04-24 20:49:52.658000 | 2022-04-24 20:49:52.761000 | 2022-04-24 20:49:53.241000 | COMPLETED | COMPLETED | | 2022-04-24 20:49:53.242000 | NULL | | 5 | 2 | 5 | 2022-04-24 21:00:08.514000 | 2022-04-24 21:00:08.618000 | 2022-04-24 21:00:09.072000 | COMPLETED | COMPLETED | | 2022-04-24 21:00:09.073000 | NULL | +------------------+---------+-----------------+----------------------------+----------------------------+----------------------------+-----------+-----------+--------------+----------------------------+----------------------------+ 5 rows in set (0.00 sec) mysql> select * from BATCH_JOB_EXECUTION_CONTEXT; +------------------+--------------------------------+--------------------+ | JOB_EXECUTION_ID | SHORT_CONTEXT | SERIALIZED_CONTEXT | +------------------+--------------------------------+--------------------+ | 1 | {"@class":"java.util.HashMap"} | NULL | | 2 | {"@class":"java.util.HashMap"} | NULL | | 3 | {"@class":"java.util.HashMap"} | NULL | | 4 | {"@class":"java.util.HashMap"} | NULL | | 5 | {"@class":"java.util.HashMap"} | NULL | +------------------+--------------------------------+--------------------+ 5 rows in set (0.01 sec) mysql> select * from BATCH_JOB_EXECUTION_PARAMS; +------------------+---------+-----------+-----------------------------------------+----------------------------+----------+------------+-------------+ | JOB_EXECUTION_ID | TYPE_CD | KEY_NAME | STRING_VAL | DATE_VAL | LONG_VAL | DOUBLE_VAL | IDENTIFYING | +------------------+---------+-----------+-----------------------------------------+----------------------------+----------+------------+-------------+ | 1 | LONG | run.id | | 1970-01-01 09:00:00.000000 | 1 | 0 | Y | | 1 | STRING | filePath | src/main/resources/book.csv | 1970-01-01 09:00:00.000000 | 0 | 0 | Y | | 2 | LONG | run.id | | 1970-01-01 09:00:00.000000 | 2 | 0 | Y | | 2 | STRING | filePath | src/main/resources/book.csv | 1970-01-01 09:00:00.000000 | 0 | 0 | Y | | 3 | LONG | run.id | | 1970-01-01 09:00:00.000000 | 1 | 0 | Y | | 3 | STRING | filePath | src/main/resources/book_with_header.csv | 1970-01-01 09:00:00.000000 | 0 | 0 | Y | | 4 | LONG | run.id | | 1970-01-01 09:00:00.000000 | 2 | 0 | Y | | 4 | STRING | hasHeader | false | 1970-01-01 09:00:00.000000 | 0 | 0 | Y | | 4 | STRING | filePath | src/main/resources/book.csv | 1970-01-01 09:00:00.000000 | 0 | 0 | Y | | 5 | LONG | run.id | | 1970-01-01 09:00:00.000000 | 1 | 0 | Y | +------------------+---------+-----------+-----------------------------------------+----------------------------+----------+------------+-------------+ 10 rows in set (0.00 sec) mysql> select * from BATCH_JOB_EXECUTION_SEQ; +----+------------+ | ID | UNIQUE_KEY | +----+------------+ | 5 | 0 | +----+------------+ 1 row in set (0.00 sec) mysql> select * from BATCH_JOB_INSTANCE; +-----------------+---------+-----------------------------+----------------------------------+ | JOB_INSTANCE_ID | VERSION | JOB_NAME | JOB_KEY | +-----------------+---------+-----------------------------+----------------------------------+ | 1 | 0 | fileLoadToDatabaseJob | 2247a3263300ca04598c73ac33b0fb7e | | 2 | 0 | fileLoadToDatabaseJob | 1062f6824a3419e049c6d95f6e5e99c2 | | 3 | 0 | fileLoadToDatabaseSimplyJob | 22f79c44e978cc2d028116a60ed9fdd5 | | 4 | 0 | fileLoadToDatabaseSimplyJob | 27f07cdb7c5117f846c1f6eec03d26de | | 5 | 0 | loggingDatabaseJob | 853d3449e311f40366811cbefb3d93d7 | +-----------------+---------+-----------------------------+----------------------------------+ 5 rows in set (0.00 sec) mysql> select * from BATCH_JOB_SEQ; +----+------------+ | ID | UNIQUE_KEY | +----+------------+ | 5 | 0 | +----+------------+ 1 row in set (0.00 sec) mysql> select * from BATCH_STEP_EXECUTION; +-------------------+---------+------------------------------+------------------+----------------------------+----------------------------+-----------+--------------+------------+--------------+-------------+-----------------+------------------+--------------------+----------------+-----------+--------------+----------------------------+ | STEP_EXECUTION_ID | VERSION | STEP_NAME | JOB_EXECUTION_ID | START_TIME | END_TIME | STATUS | COMMIT_COUNT | READ_COUNT | FILTER_COUNT | WRITE_COUNT | READ_SKIP_COUNT | WRITE_SKIP_COUNT | PROCESS_SKIP_COUNT | ROLLBACK_COUNT | EXIT_CODE | EXIT_MESSAGE | LAST_UPDATED | +-------------------+---------+------------------------------+------------------+----------------------------+----------------------------+-----------+--------------+------------+--------------+-------------+-----------------+------------------+--------------------+----------------+-----------+--------------+----------------------------+ | 1 | 6 | fileLoadToDatabaseStep | 1 | 2022-04-24 20:32:03.885000 | 2022-04-24 20:32:04.250000 | COMPLETED | 4 | 10 | 0 | 10 | 0 | 0 | 0 | 0 | COMPLETED | | 2022-04-24 20:32:04.252000 | | 2 | 6 | fileLoadToDatabaseStep | 2 | 2022-04-24 20:33:56.364000 | 2022-04-24 20:33:56.690000 | COMPLETED | 4 | 10 | 0 | 10 | 0 | 0 | 0 | 0 | COMPLETED | | 2022-04-24 20:33:56.692000 | | 3 | 6 | fileLoadToDatabaseSimplyStep | 3 | 2022-04-24 20:48:35.817000 | 2022-04-24 20:48:36.208000 | COMPLETED | 4 | 10 | 0 | 10 | 0 | 0 | 0 | 0 | COMPLETED | | 2022-04-24 20:48:36.209000 | | 4 | 6 | fileLoadToDatabaseSimplyStep | 4 | 2022-04-24 20:49:52.851000 | 2022-04-24 20:49:53.207000 | COMPLETED | 4 | 10 | 0 | 10 | 0 | 0 | 0 | 0 | COMPLETED | | 2022-04-24 20:49:53.208000 | | 5 | 3 | loggingDatabaseStep | 5 | 2022-04-24 21:00:08.698000 | 2022-04-24 21:00:09.041000 | COMPLETED | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | COMPLETED | | 2022-04-24 21:00:09.042000 | +-------------------+---------+------------------------------+------------------+----------------------------+----------------------------+-----------+--------------+------------+--------------+-------------+-----------------+------------------+--------------------+----------------+-----------+--------------+----------------------------+ 5 rows in set (0.00 sec) mysql> select * from BATCH_STEP_EXECUTION_CONTEXT; +-------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------+ | STEP_EXECUTION_ID | SHORT_CONTEXT | SERIALIZED_CONTEXT | +-------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------+ | 1 | {"@class":"java.util.HashMap","batch.taskletType":"org.springframework.batch.core.step.item.ChunkOrientedTasklet","batch.stepType":"org.springframework.batch.core.step.tasklet.TaskletStep"} | NULL | | 2 | {"@class":"java.util.HashMap","batch.taskletType":"org.springframework.batch.core.step.item.ChunkOrientedTasklet","batch.stepType":"org.springframework.batch.core.step.tasklet.TaskletStep"} | NULL | | 3 | {"@class":"java.util.HashMap","batch.taskletType":"org.springframework.batch.core.step.item.ChunkOrientedTasklet","batch.stepType":"org.springframework.batch.core.step.tasklet.TaskletStep"} | NULL | | 4 | {"@class":"java.util.HashMap","batch.taskletType":"org.springframework.batch.core.step.item.ChunkOrientedTasklet","batch.stepType":"org.springframework.batch.core.step.tasklet.TaskletStep"} | NULL | | 5 | {"@class":"java.util.HashMap","batch.taskletType":"org.littlewings.spring.batch.tasklet.LoggingBookTasklet$$EnhancerBySpringCGLIB$$7acedf7a","batch.stepType":"org.springframework.batch.core.step.tasklet.TaskletStep"} | NULL | +-------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------+ 5 rows in set (0.00 sec) mysql> select * from BATCH_STEP_EXECUTION_SEQ; +----+------------+ | ID | UNIQUE_KEY | +----+------------+ | 5 | 0 | +----+------------+ 1 row in set (0.00 sec)
ãŸãšã
Spring BatchãåããŠäœ¿ã£ãŠã¿ãŸããã
jBatchã䜿ã£ãããæ
å ±ã¯èŠãããšããã£ãã®ã§ãã£ãããšç¥ã£ãŠããã€ããã§ããããå®éã«ãœãŒã¹ã³ãŒããæžããŠåããããšãããš
ããããããããŸããŠâŠã
ä»åè©ŠããŠã¿ãŠãå°ãã¯æèŠãããã£ãããªãšæããŸãã