This is a simple Spring Batch project. This implementation will read from a database table and write to a database table via JPA.
The Maven dependency for Spring Batch is:
<dependency> <groupId>org.springframework.batch</groupId> <artifactId>spring-batch-core</artifactId> <version>${spring.batch.version}</version> </dependency>
Please note that Spring Batch does use the Spring Framework. Spring Batch 3.0.6 corresponds to Spring 4.0.5. Attempting to use a newer version of Spring will cause runtime errors.
You will also need dependencies for communicating with the database.
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>5.0.7.Final</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-dbcp2</artifactId> <version>2.1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.38</version> </dependency>
Below is my entire pom.xml.
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.javaninja</groupId> <artifactId>spring-batch-jpa</artifactId> <version>1.0-SNAPSHOT</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <!--This is the version of Spring that Spring Batch uses--> <spring.version>4.0.5.RELEASE</spring.version> <spring.batch.version>3.0.6.RELEASE</spring.batch.version> <slf4j.version>1.7.13</slf4j.version> </properties> <dependencies> <dependency> <groupId>org.springframework.batch</groupId> <artifactId>spring-batch-core</artifactId> <version>${spring.batch.version}</version> <exclusions> <exclusion> <artifactId>commons-logging</artifactId> <groupId>commons-logging</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>5.0.7.Final</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-dbcp2</artifactId> <version>2.1</version> <exclusions> <exclusion> <artifactId>commons-logging</artifactId> <groupId>commons-logging</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.38</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.4</version> </dependency> <!-- Logging --> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.1.3</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>log4j-over-slf4j</artifactId> <version>${slf4j.version}</version> </dependency> <!-- Testing --> <dependency> <groupId>org.springframework.batch</groupId> <artifactId>spring-batch-test</artifactId> <version>${spring.batch.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.3</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
You will need the standard JobRepository, JobLauncher and TransactionManager (See Database/JPA below).
<!--This repository is only really intended for use in testing and rapid prototyping--> <bean id="jobRepository" class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean"/> <bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher" p:jobRepository-ref="jobRepository"/>
The reading of data from the database via JPA is handled by a JpaPagingItemReader. The JpaPagingItemReader requires the following:
The configuration for the JpaPagingItemReader is:
<!-- ItemReader which reads data from the database --> <bean id="itemReader" class="org.springframework.batch.item.database.JpaPagingItemReader" p:entityManagerFactory-ref="entityManagerFactory" p:queryString="SELECT s FROM CamAffiliateEntity s"/>
The writing of the JPA data is handled by JpaItemWriter. The JpaItemWriter also requires an EntityManagerFactory (see JPA configuration below).
The configuration for the JpaItemWriter is:
<!-- ItemWriter which writes the data to the database --> <bean id="itemWriter" class="org.springframework.batch.item.database.JpaItemWriter" p:entityManagerFactory-ref="entityManagerFactory"/>
You will also need the following to configure the Jpa-support to read the records from the database:
Spring Batch requires a transaction manager and so does Spring’s JPA support. In this case, I’m using the same transaction manager for both. I’m not sure if this is correct, but it appears to work.
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close" p:driverClassName="com.mysql.jdbc.Driver" p:url="jdbc:mysql://database.javaninja.com/batch?zeroDateTimeBehavior=convertToNull" p:username="javaninja" p:password="javaninja"/> <!-- JPA EntityManagerFactory configuration --> <bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" p:dataSource-ref="dataSource" p:packagesToScan="com.javaninja.batch" p:jpaVendorAdapter-ref="jpaVendorAdapter"/> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"/>
The entire Spring context is below:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <import rhttps://javaninja.net/files/2016/02/esource="classpath:META-INF/spring/batchContext.xml"/> <context:component-scan base-package="com.javaninja.batch"/> <!--This repository is only really intended for use in testing and rapid prototyping--> <bean id="jobRepository" class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean"/> <bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher" p:jobRepository-ref="jobRepository"/> <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close" p:driverClassName="com.mysql.jdbc.Driver" p:url="jdbc:mysql://10.20.13.53/cam?zeroDateTimeBehavior=convertToNull" p:username="usr_ig_dev" p:password="igaming_developer"/> <!-- JPA EntityManagerFactory configuration --> <bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" p:dataSource-ref="dataSource" p:packagesToScan="com.javaninja.batch" p:jpaVendorAdapter-ref="jpaVendorAdapter"/> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"/> <!-- ItemReader which reads data from the database --> <bean id="itemReader" class="org.springframework.batch.item.database.JpaPagingItemReader" p:entityManagerFactory-ref="entityManagerFactory" p:queryString="SELECT s FROM CamAffiliateEntity s"/> <!-- ItemWriter which writes the data to the database --> <bean id="itemWriter" class="org.springframework.batch.item.database.JpaItemWriter" p:entityManagerFactory-ref="entityManagerFactory"/> </beans>
The XML configuration for the JPA batch job is pretty much the same as my other examples.
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:batch="http://www.springframework.org/schema/batch" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd"> <batch:job id="carJob"> <batch:step id="step1"> <batch:tasklet> <batch:chunk reader="itemReader" writer="itemWriter" commit-interval="10"/> </batch:tasklet> </batch:step> </batch:job> </beans>
The entire project used to write this blog is located on GitHub sheltonn / spring-batch-jpa
sheltonn February 19th, 2016
Posted In: Java, java ninja, Javaninja, Spring, Spring Batch