Spring Batch - MySQL 到 XML



本章我们将创建一个 Spring Batch 应用,它使用 MySQL 读取器和 XML 写入器。

读取器 - 应用中使用的读取器是 JdbcCursorItemReader,用于从 MySQL 数据库读取数据。

假设我们在 MySQL 数据库中创建了一个如下所示的表:

CREATE TABLE details.tutorialsdata( 
   tutorial_id int NOT NULL, 
   tutorial_author VARCHAR(20), 
   tutorial_title VARCHAR(20), 
   submission_date VARCHAR(20) 
);

假设我们向其中插入了以下记录。

mysql> select * from tutorialsdata; 
+-------------+-----------------+----------------+-----------------+ 
| tutorial_id | tutorial_author | tutorial_title | submission_date | 
+-------------+-----------------+----------------+-----------------+ 
|         101 | Sanjay          | Learn Java     | 06-05-2007      | 
|         102 | Abdul S         | Learn MySQL    | 19-04-2007      | 
|         103 | Krishna Kasyap  | Learn JavaFX   | 06-07-2017      | 
+-------------+-----------------+----------------+-----------------+ 
3 rows in set (0.00 sec) 

写入器 - 应用中使用的写入器是 StaxEventItemWriter,用于将数据写入 XML 文件。

处理器 - 应用中使用的处理器是一个自定义处理器,它只打印从 CSV 文件读取的记录。

创建项目

按照 Spring Batch - 环境配置章节中所述,创建一个新的 Maven 项目。

pom.xml

以下是此 Maven 项目中使用的 pom.xml 文件的内容。

<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/maven-v4_0_0.xsd"> 
   <modelVersion>4.0.0</modelVersion> 
   <groupId>com.tutorialspoint</groupId> 
   <artifactId>SpringBatchSample</artifactId> 
   <packaging>jar</packaging> 
   <version>1.0-SNAPSHOT</version> 
   <name>SpringBatchExample</name>
   <url>http://maven.apache.org</url>  

   <properties> 
      <jdk.version>21</jdk.version> 
      <spring.version>5.3.14</spring.version> 
      <spring.batch.version>4.3.4</spring.batch.version> 
      <mysql.driver.version>8.4.0</mysql.driver.version> 
      <junit.version>4.11</junit.version> 
      <pdf.version>2.0.32</pdf.version>
      <xstream.version>1.4.17</xstream.version>
      <jaxb.version>2.3.1</jaxb.version> 
      <jaxb.impl.version>2.3.4</jaxb.impl.version> 
   </properties>  

   <dependencies> 
      <!-- Spring Core --> 
      <dependency> 
         <groupId>org.springframework</groupId> 
         <artifactId>spring-core</artifactId> 
         <version>${spring.version}</version> 
      </dependency>  

      <!-- Spring jdbc, for database --> 
      <dependency> 
         <groupId>org.springframework</groupId> 
         <artifactId>spring-jdbc</artifactId> 
         <version>${spring.version}</version> 
      </dependency>  

      <!-- Spring XML to/back object --> 
      <dependency> 
         <groupId>org.springframework</groupId> 
         <artifactId>spring-oxm</artifactId> 
         <version>${spring.version}</version> 
      </dependency>  

      <!-- MySQL database driver --> 
      <dependency>
         <groupId>com.mysql</groupId>
         <artifactId>mysql-connector-j</artifactId>
         <version>${mysql.driver.version}</version>
      </dependency>  

      <!-- Spring Batch dependencies --> 
      <dependency> 
         <groupId>org.springframework.batch</groupId> 
         <artifactId>spring-batch-core</artifactId> 
         <version>${spring.batch.version}</version> 
      </dependency> 

      <dependency> 
         <groupId>org.springframework.batch</groupId> 
         <artifactId>spring-batch-infrastructure</artifactId> 
         <version>${spring.batch.version}</version> 
      </dependency>  

      <!-- Spring Batch unit test --> 
      <dependency> 
         <groupId>org.springframework.batch</groupId> 
         <artifactId>spring-batch-test</artifactId> 
         <version>${spring.batch.version}</version> 
      </dependency>  

      <!-- Junit --> 
      <dependency> 
         <groupId>junit</groupId> 
         <artifactId>junit</artifactId> 
         <version>${junit.version}</version> 
         <scope>test</scope> 
      </dependency> 

      <!-- pdfbox -->
      <dependency>
         <groupId>org.apache.pdfbox</groupId>
         <artifactId>pdfbox</artifactId>
         <version>${pdf.version}</version>
      </dependency>
	  
      <!-- xstream -->
      <dependency>
         <groupId>com.thoughtworks.xstream</groupId>
         <artifactId>xstream</artifactId>
         <version>${xstream.version}</version>
      </dependency>
	  
      <!-- jaxb-api -->
      <dependency>
         <groupId>javax.xml.bind</groupId>
         <artifactId>jaxb-api</artifactId>
         <version>${jaxb.version}</version>
      </dependency>
	  
      <!-- JAXB RI -->
      <dependency>
         <groupId>com.sun.xml.bind</groupId>
         <artifactId>jaxb-impl</artifactId>
         <version>${jaxb.impl.version}</version>
      </dependency>

   </dependencies> 

   <build> 
      <finalName>spring-batch</finalName> 
      <plugins> 
         <plugin> 
            <groupId>org.apache.maven.plugins</groupId> 
            <artifactId>maven-eclipse-plugin</artifactId>
            <version>2.9</version> 
            <configuration> 
               <downloadSources>true</downloadSources> 
               <downloadJavadocs>false</downloadJavadocs> 
            </configuration> 
         </plugin> 
   
         <plugin> 
            <groupId>org.apache.maven.plugins</groupId> 
            <artifactId>maven-compiler-plugin</artifactId> 
            <version>2.3.2</version> 
            <configuration> 
               <source>${jdk.version}</source> 
               <target>${jdk.version}</target> 
            </configuration> 
         </plugin> 
      </plugins> 
   </build> 
</project>    

jobConfig.xml

以下是我们的 Spring Batch 示例应用程序的配置文件。在此文件中,我们将定义作业和步骤。此外,我们还定义了 ItemReader、ItemProcessor 和 ItemWriter 的 bean。(在这里,我们将它们与各自的类关联,并传递所需属性的值来配置它们。)

在 Maven 项目的 src > main > resources 文件夹中创建此文件。

<beans xmlns = "http://www.springframework.org/schema/beans" 
   xmlns:batch = "http://www.springframework.org/schema/batch" 
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" 
   xmlns:util = "http://www.springframework.org/schema/util" 
   xsi:schemaLocation = " http://www.springframework.org/schema/batch 
      http://www.springframework.org/schema/batch/spring-batch-2.2.xsd 
      http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">  
   
   <import resource = "context.xml" /> 
  
   <bean id = "report" class = "Report" scope = "prototype" /> 
   <bean id = "itemProcessor" class = "CustomItemProcessor" />  
   
   <batch:job id = "helloWorldJob"> 
      <batch:step id = "step1"> 
         <batch:tasklet> 
            <batch:chunk reader = "dbItemReader" 
               writer = "mysqlItemWriter" processor = "itemProcessor" commit-interval = "10">
            </batch:chunk> 
         </batch:tasklet> 
      </batch:step> 
   </batch:job> 
         
   <bean id = "dbItemReader" 
      class = "org.springframework.batch.item.database.JdbcCursorItemReader" scope = "step"> 
      <property name = "dataSource" ref = "dataSource" /> 
      <property name = "sql" value = "select * from tutorialsdata" /> 
      <property name = "rowMapper"> 
         <bean class = "TutorialRowMapper" /> 
      </property> 
   </bean>             
   <bean id = "mysqlItemWriter" 
      class = "org.springframework.batch.item.xml.StaxEventItemWriter"> 
      <property name = "resource" value = "file:tutorials.xml" /> 
      <property name = "marshaller" ref = "reportMarshaller" />
      <property name = "rootTagName" value = "tutorials" /> 
   </bean>  
   
   <bean id = "reportMarshaller" class = "org.springframework.oxm.jaxb.Jaxb2Marshaller"> 
      <property name = "classesToBeBound"> 
         <list> 
            <value>Tutorial</value> 
         </list> 
      </property> 
   </bean> 
</beans>  

Context.xml

以下是我们的 Spring Batch 应用程序的 context.xml 文件。在此文件中,我们将定义诸如作业存储库、作业启动器和事务管理器之类的 bean。

在 Maven 项目的 src > main > resources 文件夹中创建此文件。

<beans xmlns = " http://www.springframework.org/schema/beans" 
   xmlns:jdbc = "http://www.springframework.org/schema/jdbc" 
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" 
   xsi:schemaLocation = "http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
      http://www.springframework.org/schema/jdbc 
      http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd "> 
   
   <!-- stored job-meta in database --> 
   <bean id = "jobRepository"  
      class = "org.springframework.batch.core.repository.support.JobRepositoryFactoryBean"> 
      <property name = "dataSource" ref = "dataSource" /> 
      <property name = "transactionManager" ref = "transactionManager" /> 
      <property name = "databaseType" value = "mysql" /> 
   </bean>  
   
   <bean id = "transactionManager" 
      class = "org.springframework.batch.support.transaction.ResourcelessTransactionMana ger" />  
   <bean id = "jobLauncher"
      class = "org.springframework.batch.core.launch.support.SimpleJobLauncher"> 
      <property name = "jobRepository" ref = "jobRepository" /> 
   </bean> 
  
   <!-- connect to MySQL database --> 
   <bean id = "dataSource" 
      class = "org.springframework.jdbc.datasource.DriverManagerDataSource"> 
      <property name = "url" value = "jdbc:mysql://127.0.0.1:3306/details" /> 
      <property name = "username" value = "myuser" /> 
      <property name = "password" value = "password" /> 
   </bean> 
  
   <!-- create job-meta tables automatically --> 
   <jdbc:initialize-database data-source = "dataSource">   
      <jdbc:script location = "org/springframework/batch/core/schema-drop-mysql.sql" />   
      <jdbc:script location = "org/springframework/batch/core/schema-mysql.sql" /> 
   </jdbc:initialize-database> 
</beans>  

CustomItemProcessor.java

以下是处理器类。在这个类中,我们编写应用程序的处理代码。在这里,我们打印每条记录的内容。

在 Maven 项目的 src > main > java 文件夹中创建此类。

import org.springframework.batch.item.ItemProcessor;  

public class CustomItemProcessor implements ItemProcessor<Tutorial, Tutorial> {  

   @Override 
   public Tutorial process(Tutorial item) throws Exception { 
      System.out.println("Processing..." + item); 
      return item; 
   } 
} 

TutorialRowMapper.java

以下是 TutorialRowMapper 类,它将数据设置到 Tutorial 类。

在 Maven 项目的 src > main > java 文件夹中创建此类。

import java.sql.ResultSet; 
import java.sql.SQLException; 
import org.springframework.jdbc.core.RowMapper;  

public class TutorialRowMapper implements RowMapper<Tutorial> {  
   
   @Override 
   public Tutorial mapRow(ResultSet rs, int rowNum) throws SQLException {  
      
      Tutorial tutorial = new Tutorial();  
      tutorial.setTutorial_id(rs.getInt("tutorial_id")); 
      tutorial.setTutorial_author(rs.getString("tutorial_author")); 
      tutorial.setTutorial_title(rs.getString("tutorial_title")); 
      tutorial.setSubmission_date(rs.getString("submission_date"));  
      return tutorial; 
   } 
}

Tutorial.java

以下是 Tutorial 类。这是一个简单的 Java 类,带有 settergetter 方法。在这个类中,我们使用注解将此类的使用方法与 XML 文件的标签关联。

在 Maven 项目的 src > main > java 文件夹中创建此类。

import javax.xml.bind.annotation.XmlAttribute; 
import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement(name = "tutorial") 
public class Tutorial {  
   private int tutorial_id; 
   private String tutorial_author; 
   private String tutorial_title;
   private String submission_date;  
 
   @XmlAttribute(name = "tutorial_id") 
   public int getTutorial_id() { 
      return tutorial_id; 
   }  
 
   public void setTutorial_id(int tutorial_id) { 
      this.tutorial_id = tutorial_id; 
   }  
 
   @XmlElement(name = "tutorial_author") 
   public String getTutorial_author() { 
      return tutorial_author; 
   }  
   public void setTutorial_author(String tutorial_author) { 
      this.tutorial_author = tutorial_author; 
   }  
      
   @XmlElement(name = "tutorial_title") 
   public String getTutorial_title() { 
      return tutorial_title; 
   }  
   
   public void setTutorial_title(String tutorial_title) { 
      this.tutorial_title = tutorial_title; 
   }  
   
   @XmlElement(name = "submission_date") 
   public String getSubmission_date() { 
      return submission_date; 
   }  
   
   public void setSubmission_date(String submission_date) { 
      this.submission_date = submission_date; 
   } 
   
   @Override 
   public String toString() { 
      return "  [Tutorial id=" + tutorial_id + 
         ",Tutorial Author=" + tutorial_author  + 
         ",Tutorial Title=" + tutorial_title + 
         ",Submission Date=" + submission_date + "]"; 
   } 
}  

App.java

以下是启动批处理过程的代码。在这个类中,我们将通过运行 JobLauncher 来启动 Batch 应用程序。

在 Maven 项目的 src > main > java 文件夹中创建此类。

import org.springframework.batch.core.Job; 
import org.springframework.batch.core.JobExecution; 
import org.springframework.batch.core.JobParameters; 
import org.springframework.batch.core.launch.JobLauncher; 
import org.springframework.context.ApplicationContext; 
import org.springframework.context.support.ClassPathXmlApplicationContext;  

public class App {  
   public static void main(String[] args) throws Exception { 
     
      String[] springConfig  =  { "jobConfig.xml" };  
      
      // Creating the application context object  
      ApplicationContext context = new ClassPathXmlApplicationContext(springConfig);  
      
      // Creating the job launcher 
      JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher"); 
    
      // Creating the job 
      Job job = (Job) context.getBean("helloWorldJob");
      
      // Executing the JOB 
      JobExecution execution = jobLauncher.run(job, new JobParameters()); 
      System.out.println("Exit Status : " + execution.getStatus()); 
   } 
}      

输出

在 Eclipse 中右键单击项目,选择 运行方式 -> Maven 构建。将目标设置为 clean package 并运行项目。您将看到以下输出。

[INFO] Scanning for projects...
[INFO] 
[INFO] [1m----------------< [0;36mcom.tutorialspoint:SpringBatchSample[0;1m >----------------[m
[INFO] [1mBuilding SpringBatchExample 1.0-SNAPSHOT[m
[INFO]   from pom.xml
[INFO] [1m--------------------------------[ jar ]---------------------------------[m
[INFO] 
[INFO] [1m--- [0;32mclean:3.2.0:clean[m [1m(default-clean)[m @ [36mSpringBatchSample[0;1m ---[m
[INFO] Deleting C:\Users\Tutorialspoint\eclipse-workspace\SpringBatchSample\target
[INFO] 
[INFO] [1m--- [0;32mresources:3.3.1:resources[m [1m(default-resources)[m @ [36mSpringBatchSample[0;1m ---[m
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 4 resources from src\main\resources to target\classes
[INFO] 
[INFO] [1m--- [0;32mcompiler:2.3.2:compile[m [1m(default-compile)[m @ [36mSpringBatchSample[0;1m ---[m
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 5 source files to C:\Users\Tutorialspoint\eclipse-workspace\SpringBatchSample\target\classes
[INFO] 
[INFO] [1m--- [0;32mresources:3.3.1:testResources[m [1m(default-testResources)[m @ [36mSpringBatchSample[0;1m ---[m
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource from src\test\resources to target\test-classes
[INFO] 
[INFO] [1m--- [0;32mcompiler:2.3.2:testCompile[m [1m(default-testCompile)[m @ [36mSpringBatchSample[0;1m ---[m
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] [1m--- [0;32msurefire:3.1.2:test[m [1m(default-test)[m @ [36mSpringBatchSample[0;1m ---[m
[INFO] 
[INFO] [1m--- [0;32mjar:3.3.0:jar[m [1m(default-jar)[m @ [36mSpringBatchSample[0;1m ---[m
[INFO] Building jar: C:\Users\Tutorialspoint\eclipse-workspace\SpringBatchSample\target\spring-batch.jar
[INFO] [1m------------------------------------------------------------------------[m
[INFO] [1;32mBUILD SUCCESS[m
[INFO] [1m------------------------------------------------------------------------[m
[INFO] Total time:  3.323 s
[INFO] Finished at: 2024-07-31T12:54:04+05:30
[INFO] [1m------------------------------------------------------------------------[m

要检查上述 Spring Batch 程序的输出,请右键单击 App.java 类,然后选择 运行方式 -> Java 应用程序。它将产生以下输出:

Jul 31, 2024 1:24:13 PM org.springframework.batch.core.launch.support.SimpleJobLauncher afterPropertiesSet
INFO: No TaskExecutor has been set, defaulting to synchronous executor.
Jul 31, 2024 1:24:16 PM org.springframework.batch.core.launch.support.SimpleJobLauncher$1 run
INFO: Job: [FlowJob: [name=helloWorldJob]] launched with the following parameters: [{}]
Jul 31, 2024 1:24:16 PM org.springframework.batch.core.job.SimpleStepHandler handleStep
INFO: Executing step: [step1]
Processing...  [Tutorial id=101,Tutorial Author=Sanjay,Tutorial Title=Learn Java,Submission Date=06-05-2007]
Processing...  [Tutorial id=102,Tutorial Author=Abdul S,Tutorial Title=Learn MySQL,Submission Date=19-04-2007]
Processing...  [Tutorial id=103,Tutorial Author=Krishna Kasyap,Tutorial Title=Learn JavaFX,Submission Date=06-07-2017]
Jul 31, 2024 1:24:16 PM org.springframework.batch.core.step.AbstractStep execute
INFO: Step: [step1] executed in 312ms
Jul 31, 2024 1:24:16 PM org.springframework.batch.core.launch.support.SimpleJobLauncher$1 run
INFO: Job: [FlowJob: [name=helloWorldJob]] completed with the following parameters: [{}] and the following status: [COMPLETED] in 666ms
Exit Status : COMPLETED

这将生成一个 XML 文件(根文件夹中的 tutorials.xml),其内容如下。

<?xml version="1.0" encoding="UTF-8"?>
<tutorials>
   <tutorial tutorial_id="101">
      <submission_date>06-05-2007</submission_date>
      <tutorial_author>Sanjay</tutorial_author>
      <tutorial_title>Learn Java</tutorial_title>
   </tutorial>
   <tutorial tutorial_id="102">
      <submission_date>19-04-2007</submission_date>
      <tutorial_author>Abdul S</tutorial_author>
      <tutorial_title>Learn MySQL</tutorial_title>
   </tutorial>
   <tutorial tutorial_id="103">
      <submission_date>06-07-2017</submission_date>
      <tutorial_author>Krishna Kasyap</tutorial_author>
      <tutorial_title>Learn JavaFX</tutorial_title>
   </tutorial>
</tutorials>
广告