Trang chủHướng dẫnVí dụ về Spring Batch
Java

Ví dụ về Spring Batch

CyStack blog 9 phút để đọc
CyStack blog23/10/2025
Locker Avatar

Bao Tran

Web Developer

Locker logo social
Reading Time: 9 minutes

Spring Batch là một công cụ mạnh mẽ, được xây dựng dựa trên Spring Framework, chuyên biệt cho việc phát triển các ứng dụng batch với khả năng mở rộng và khả năng quản lý lỗi ưu việt. Nó cung cấp một kiến trúc rõ ràng và các thành phần có thể tái sử dụng, giúp bạn dễ dàng thiết kế và triển khai các tác vụ phức tạp một cách hiệu quả.

Giới thiệu về Spring Batch

Trước khi chúng ta bắt tay vào ví dụ chương trình Spring Batch, hãy cùng nắm bắt một vài thuật ngữ quan trọng của Spring Batch:

  • Job: Một Job có thể bao gồm n số lượng Step. Mỗi Step chứa một tác vụ Read-Process-Write hoặc nó có thể có một hoạt động duy nhất, được gọi là Tasklet.
  • Read-Process-Write: Về cơ bản, Read-Process-Write là quá trình đọc dữ liệu từ một nguồn (như Database, CSV, v.v.), sau đó xử lý dữ liệu và ghi nó ra một nguồn đích (như Database, CSV, XML, v.v.).
  • Tasklet: Tasklet đơn giản là việc thực hiện một tác vụ hoặc thao tác duy nhất, chẳng hạn như dọn dẹp các kết nối, giải phóng tài nguyên sau khi quá trình xử lý hoàn tất.
  • Read-Process-WriteTasklet lại với nhau để chạy một Job hoàn chỉnh.

Ví dụ Spring Batch

Chúng ta sẽ xem xét một ví dụ thực tế để triển khai Spring Batch. Kịch bản của chúng ta là: một tệp CSV chứa dữ liệu cần được chuyển đổi sang định dạng XML. Các thẻ (tags) trong XML sẽ được đặt tên theo tên cột của dữ liệu.

Dưới đây là các công cụ và thư viện quan trọng chúng ta sử dụng cho ví dụ Spring Batch này:

  • Apache Maven 3.5.0: Để quản lý build dự án và các thư viện phụ thuộc.
  • Eclipse Oxygen Release 4.7.0: Môi trường phát triển tích hợp (IDE) để tạo ứng dụng Spring Batch Maven.
  • Java 1.8
  • Spring Core 4.3.12.RELEASE
  • Spring OXM 4.3.12.RELEASE
  • Spring JDBC 4.3.12.RELEASE
  • Spring Batch 3.0.8.RELEASE
  • MySQL Java Driver 5.1.25: Sử dụng dựa trên cài đặt MySQL của bạn. Cái này cần thiết cho các bảng metadata của Spring Batch.

Cấu trúc thư mục dự án Spring Batch

Dưới đây là một mô tả về các thành phần trong dự án Spring Batch ví dụ của chúng ta.

Maven Dependencies cho Spring Batch

Dưới đây là nội dung tệp pom.xml với tất cả các thư viện phụ thuộc cần thiết cho dự án Spring Batch ví dụ của chúng ta. Bạn cần thêm các dependency này để Maven có thể tải và quản lý các thư viện cần thiết cho ứng dụng.

<project xmlns="<https://maven.apache.org/POM/4.0.0>" xmlns:xsi="<https://www.w3.org/2001/XMLSchema-instance>"
	xsi:schemaLocation="<https://maven.apache.org/POM/4.0.0> <https://maven.apache.org/xsd/maven-4.0.0.xsd>">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.journaldev.spring</groupId>
	<artifactId>SpringBatchExample</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>SpringBatchDemo</name>
	<url><https://maven.apache.org></url>

	<properties>
		<jdk.version>1.8</jdk.version>
		<spring.version>4.3.12.RELEASE</spring.version>
		<spring.batch.version>3.0.8.RELEASE</spring.batch.version>
		<mysql.driver.version>5.1.25</mysql.driver.version>
		<junit.version>4.11</junit.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>mysql</groupId>
			<artifactId>mysql-connector-java</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>

		<dependency>
			<groupId>com.thoughtworks.xstream</groupId>
			<artifactId>xstream</artifactId>
			<version>1.4.10</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>
		</build>
</project>

Tệp Input CSV cho Spring Batch Processing

Đây là nội dung tệp CSV mẫu của chúng ta cho quá trình xử lý Spring Batch. Bạn hãy tạo một tệp report.csv trong thư mục src/main/resources/csv/input/.

1001,Tom,Moody, 29/7/2013
1002,John,Parker, 30/7/2013
1003,Henry,Williams, 31/7/2013

Cấu hình Spring Batch Job

Chúng ta phải định nghĩa các spring beanspring batch job trong một tệp cấu hình. Dưới đây là nội dung của tệp job-batch-demo.xml, đây là phần quan trọng nhất của dự án Spring Batch. Bạn sẽ đặt tệp này trong thư mục src/main/resources/spring/batch/jobs/.

job-batch-demo.xml

<beans xmlns="<https://www.springframework.org/schema/beans>"
	xmlns:batch="<https://www.springframework.org/schema/batch>" xmlns:xsi="<https://www.w3.org/2001/XMLSchema-instance>"
	xsi:schemaLocation="<https://www.springframework.org/schema/batch>
		<https://www.springframework.org/schema/batch/spring-batch-3.0.xsd>
		<https://www.springframework.org/schema/beans>
		<https://www.springframework.org/schema/beans/spring-beans-4.3.xsd>
	">

	<import resource="../config/context.xml" />
	<import resource="../config/database.xml" />

	<bean id="report" class="com.journaldev.spring.model.Report"
		scope="prototype" />
	<bean id="itemProcessor" class="com.journaldev.spring.CustomItemProcessor" />

	<batch:job id="DemoJobXMLWriter">
		<batch:step id="step1">
			<batch:tasklet>
				<batch:chunk reader="csvFileItemReader" writer="xmlItemWriter"
					processor="itemProcessor" commit-interval="10">
				</batch:chunk>
			</batch:tasklet>
		</batch:step>
	</batch:job>

	<bean id="csvFileItemReader" class="org.springframework.batch.item.file.FlatFileItemReader">

		<property name="resource" value="classpath:csv/input/report.csv" />

		<property name="lineMapper">
			<bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
				<property name="lineTokenizer">
					<bean
						class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
						<property name="names" value="id,firstname,lastname,dob" />
					</bean>
				</property>
				<property name="fieldSetMapper">
					<bean class="com.journaldev.spring.ReportFieldSetMapper" />

					<!-- if no data type conversion, use BeanWrapperFieldSetMapper to map
						by name <bean class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
						<property name="prototypeBeanName" value="report" /> </bean> -->
				</property>
			</bean>
		</property>

	</bean>

	<bean id="xmlItemWriter" class="org.springframework.batch.item.xml.StaxEventItemWriter">
		<property name="resource" value="file:xml/outputs/report.xml" />
		<property name="marshaller" ref="reportMarshaller" />
		<property name="rootTagName" value="report" />
	</bean>

	<bean id="reportMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
		<property name="classesToBeBound">
			<list>
				<value>com.journaldev.spring.model.Report</value>
			</list>
		</property>
	</bean>

</beans>

Chúng ta đang sử dụng FlatFileItemReader để đọc tệp CSV, CustomItemProcessor để xử lý dữ liệu và ghi vào tệp XML bằng StaxEventItemWriter.

Hãy phân tích các thành phần chính:

  • batch:job: Thẻ này định nghĩa job mà chúng ta muốn tạo. Thuộc tính id chỉ định ID của job. Bạn có thể định nghĩa nhiều job trong một tệp XML duy nhất.
  • batch:step: Thẻ này dùng để định nghĩa các bước khác nhau của một job Spring Batch.
  • batch:chunk: Spring Batch Framework cung cấp hai kiểu xử lý chính: “TaskletStep Oriented” và “Chunk Oriented”. Trong ví dụ này, chúng ta sử dụng kiểu “Chunk Oriented”, nghĩa là bạn đọc dữ liệu từng mục một, xử lý nó và sau đó ghi các “chunk” (khối) dữ liệu ra trong phạm vi một giao dịch.
  • reader: spring bean được sử dụng để đọc dữ liệu. Chúng ta sử dụng csvFileItemReader trong ví dụ này, là một thể hiện của FlatFileItemReader.
  • processor: Đây là lớp dùng để xử lý dữ liệu. Chúng ta sử dụng CustomItemProcessor trong ví dụ này.
  • writer: bean được sử dụng để ghi dữ liệu vào tệp XML.
  • commit-interval: Thuộc tính này định nghĩa kích thước của chunk sẽ được commit sau khi quá trình xử lý hoàn tất. Về cơ bản, nó có nghĩa là ItemReader sẽ đọc dữ liệu từng dòng một và ItemProcessor cũng sẽ xử lý theo cách tương tự, nhưng ItemWriter chỉ ghi dữ liệu khi số lượng mục đạt đến kích thước của commit-interval.
  • Ba giao diện quan trọng được sử dụng trong dự án này là ItemReader, ItemProcessorItemWriter từ gói org.springframework.batch.item.

Lớp Model Spring Batch

Đầu tiên, chúng ta đọc tệp CSV vào đối tượng Java và sau đó sử dụng JAXB để ghi nó ra tệp XML. Dưới đây là lớp model của chúng ta với các annotation JAXB cần thiết. Bạn hãy tạo lớp Report.java trong gói com.journaldev.spring.model.

package com.journaldev.spring.model;

import java.util.Date;

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

@XmlRootElement(name = "record")
public class Report {

	private int id;
	private String firstName;
	private String lastName;
	private Date dob;

	@XmlAttribute(name = "id")
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	@XmlElement(name = "firstname")
	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	@XmlElement(name = "lastname")
	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	@XmlElement(name = "dob")
	public Date getDob() {
		return dob;
	}

	public void setDob(Date dob) {
		this.dob = dob;
	}

	@Override
	public String toString() {
		return "Report [id=" + id + ", firstname=" + firstName + ", lastName=" + lastName + ", DateOfBirth=" + dob
				+ "]";
	}

}

Lưu ý rằng các trường của lớp model phải giống với các trường được định nghĩa trong cấu hình spring batch mapper của chúng ta, tức là property name="names" value="id,firstname,lastname,dob" trong tệp XML cấu hình FlatFileItemReader.

Spring Batch FieldSetMapper

Chúng ta cần một FieldSetMapper tùy chỉnh để chuyển đổi định dạng Date từ String trong CSV sang đối tượng Date trong Java. Nếu không yêu cầu chuyển đổi kiểu dữ liệu, chúng ta có thể sử dụng BeanWrapperFieldSetMapper để tự động ánh xạ các giá trị theo tên. Lớp Java của chúng ta mở rộng FieldSetMapperReportFieldSetMapper. Bạn hãy tạo lớp này trong gói com.journaldev.spring.

package com.journaldev.spring;

import java.text.ParseException;
import java.text.SimpleDateFormat;

import org.springframework.batch.item.file.mapping.FieldSetMapper;
import org.springframework.batch.item.file.transform.FieldSet;
import org.springframework.validation.BindException;

import com.journaldev.spring.model.Report;

public class ReportFieldSetMapper implements FieldSetMapper<Report> {

	private SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");

	public Report mapFieldSet(FieldSet fieldSet) throws BindException {

		Report report = new Report();
		report.setId(fieldSet.readInt(0));
		report.setFirstName(fieldSet.readString(1));
		report.setLastName(fieldSet.readString(2));

		// default format yyyy-MM-dd
		// fieldSet.readDate(4);
		String date = fieldSet.readString(3);
		try {
			report.setDob(dateFormat.parse(date));
		} catch (ParseException e) {
			e.printStackTrace();
		}

		return report;

	}

}

Spring Batch Item Processor

Như đã định nghĩa trong cấu hình job, một itemProcessor sẽ được kích hoạt trước itemWriter. Chúng ta đã tạo lớp CustomItemProcessor.java cho mục đích này. Lớp này sẽ xử lý dữ liệu trước khi nó được ghi ra. Bạn hãy tạo lớp này trong gói com.journaldev.spring.

package com.journaldev.spring;

import org.springframework.batch.item.ItemProcessor;

import com.journaldev.spring.model.Report;

public class CustomItemProcessor implements ItemProcessor<Report, Report> {

	public Report process(Report item) throws Exception {

		System.out.println("Processing..." + item);
		String fname = item.getFirstName();
		String lname = item.getLastName();

		item.setFirstName(fname.toUpperCase());
		item.setLastName(lname.toUpperCase());
		return item;
	}

}

Bạn có thể thao tác dữ liệu trong triển khai ItemProcessor. Như bạn thấy, tôi đang chuyển đổi giá trị của firstNamelastName thành chữ in hoa. Đây là nơi bạn đặt logic nghiệp vụ để biến đổi dữ liệu.

Các tệp cấu hình Spring

Trong tệp cấu hình Spring Batch của chúng ta (job-batch-demo.xml), chúng ta đã import hai tệp cấu hình bổ sung: context.xmldatabase.xml. Bạn hãy tạo các tệp này trong thư mục src/main/resources/config/.

context.xml

<beans xmlns="<https://www.springframework.org/schema/beans>"
	xmlns:xsi="<https://www.w3.org/2001/XMLSchema-instance>"
	xsi:schemaLocation="
		<https://www.springframework.org/schema/beans>
		<https://www.springframework.org/schema/beans/spring-beans-4.3.xsd>">

	<!-- stored job-meta in memory -->
	<!--
	<bean id="jobRepository"
		class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
		<property name="transactionManager" ref="transactionManager" />
	</bean>
 	 -->

 	 <!-- 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.ResourcelessTransactionManager" />

	<bean id="jobLauncher"
		class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
		<property name="jobRepository" ref="jobRepository" />
	</bean>

</beans>

Chúng ta cùng nhau giải thích các bean quan trọng trong context.xml:

  • jobRepository: JobRepository chịu trách nhiệm lưu trữ từng đối tượng Java vào các bảng meta-data tương ứng của Spring Batch.
  • transactionManager: Cái này chịu trách nhiệm commit giao dịch khi kích thước commit-interval và dữ liệu đã xử lý bằng nhau.
  • jobLauncher: Đây là trái tim của Spring Batch. Giao diện này chứa phương thức run được sử dụng để kích hoạt một job.

database.xml

<beans xmlns="<https://www.springframework.org/schema/beans>"
	xmlns:jdbc="<https://www.springframework.org/schema/jdbc>" xmlns:xsi="<https://www.w3.org/2001/XMLSchema-instance>"
	xsi:schemaLocation="<https://www.springframework.org/schema/beans>
		<https://www.springframework.org/schema/beans/spring-beans-4.3.xsd>
		<https://www.springframework.org/schema/jdbc>
		<https://www.springframework.org/schema/jdbc/spring-jdbc-4.3.xsd>">

	<!-- connect to database -->
	<bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="url" value="jdbc:mysql://localhost:3306/Test" />
		<property name="username" value="test" />
		<property name="password" value="test123" />
	</bean>

	<bean id="transactionManager"
		class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />

	<!-- 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>

Spring Batch sử dụng một số bảng metadata để lưu trữ thông tin job batch. Bạn có thể để chúng được tạo tự động từ cấu hình Spring Batch, nhưng tốt hơn hết là tạo chúng thủ công bằng cách thực thi các tệp SQL. Về mặt bảo mật, tốt hơn là không cấp quyền thực thi DDL (Data Definition Language) cho người dùng cơ sở dữ liệu của Spring Batch.

Các bảng Spring Batch

Các bảng Spring Batch khớp rất chặt chẽ với các đối tượng Domain đại diện cho chúng trong Java. Ví dụ: JobInstance, JobExecution, JobParametersStepExecution lần lượt ánh xạ tới BATCH_JOB_INSTANCE, BATCH_JOB_EXECUTION, BATCH_JOB_EXECUTION_PARAMSBATCH_STEP_EXECUTION. ExecutionContext ánh xạ tới cả BATCH_JOB_EXECUTION_CONTEXTBATCH_STEP_EXECUTION_CONTEXT. JobRepository chịu trách nhiệm lưu và lưu trữ từng đối tượng Java vào bảng chính xác của nó.

Dưới đây là chi tiết về từng bảng meta-data:

  • BATCH_JOB_INSTANCE: Bảng này lưu trữ tất cả thông tin liên quan đến một JobInstance.
  • BATCH_JOB_EXECUTION_PARAMS: Bảng này lưu trữ tất cả thông tin liên quan đến đối tượng JobParameters.
  • BATCH_JOB_EXECUTION: Bảng này lưu trữ dữ liệu liên quan đến đối tượng JobExecution. Một hàng mới được thêm vào mỗi khi một Job được chạy.
  • BATCH_STEP_EXECUTION: Bảng này lưu trữ tất cả thông tin liên quan đến đối tượng StepExecution.
  • BATCH_JOB_EXECUTION_CONTEXT: Bảng này lưu trữ dữ liệu liên quan đến ExecutionContext của một Job. Có chính xác một Job ExecutionContext cho mỗi JobExecution, và nó chứa tất cả dữ liệu cấp job cần thiết cho việc thực thi job cụ thể đó. Dữ liệu này thường đại diện cho trạng thái phải được truy xuất sau khi một lỗi xảy ra để một JobInstance có thể khởi động lại từ nơi nó đã thất bại.
  • BATCH_STEP_EXECUTION_CONTEXT: Bảng này lưu trữ dữ liệu liên quan đến ExecutionContext của một Step. Có chính xác một ExecutionContext cho mỗi StepExecution, và nó chứa tất cả dữ liệu cần được lưu trữ cho một lần thực thi step cụ thể. Dữ liệu này thường đại diện cho trạng thái phải được truy xuất sau khi một lỗi xảy ra để một JobInstance có thể khởi động lại từ nơi nó đã thất bại.
  • BATCH_JOB_EXECUTION_SEQ: Bảng này lưu trữ dữ liệu về chuỗi thực thi của job.
  • BATCH_STEP_EXECUTION_SEQ: Bảng này lưu trữ dữ liệu về chuỗi thực thi step.
  • BATCH_JOB_SEQ: Bảng này lưu trữ dữ liệu về chuỗi job trong trường hợp chúng ta có nhiều job, chúng ta sẽ nhận được nhiều hàng.

Chương trình Test Spring Batch

Dự án Spring Batch ví dụ của chúng ta đã sẵn sàng. Bước cuối cùng là viết một lớp kiểm thử để thực thi nó như một chương trình Java độc lập. Bạn hãy tạo lớp App.java trong gói com.journaldev.spring.

package com.journaldev.spring;

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

public class App {
	public static void main(String[] args) {

		String[] springConfig = { "spring/batch/jobs/job-batch-demo.xml" };

		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(springConfig);

		JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher");
		Job job = (Job) context.getBean("DemoJobXMLWriter");

		JobParameters jobParameters = new JobParametersBuilder().addLong("time", System.currentTimeMillis())
				.toJobParameters();

		try {

			JobExecution execution = jobLauncher.run(job, jobParameters);
			System.out.println("Exit Status : " + execution.getStatus());

		} catch (Exception e) {
			e.printStackTrace();
		}

		System.out.println("Done");
		context.close();
	}
}

Bạn chỉ cần chạy chương trình trên và bạn sẽ nhận được tệp XML đầu ra như dưới đây trong thư mục xml/outputs/ của dự án bạn.

<?xml version="1.0" encoding="UTF-8"?><report><record id="1001"><dob>2013-07-29T00:00:00+05:30</dob><firstname>TOM</firstname><lastname>MOODY</lastname></record><record id="1002"><dob>2013-07-30T00:00:00+05:30</dob><firstname>JOHN</firstname><lastname>PARKER</lastname></record><record id="1003"><dob>2013-07-31T00:00:00+05:30</dob><firstname>HENRY</firstname><lastname>WILLIAMS</lastname></record></report>

Kết luận

Qua bài viết này, chúng ta đã khám phá Spring Batch, một module của Spring Framework giúp bạn thực thi các batch job một cách hiệu quả và tin cậy. Với kiến thức này, bạn có thể tự tin áp dụng Spring Batch vào các tác vụ xử lý dữ liệu thực tế trong công việc của mình.

0 Bình luận

Đăng nhập để thảo luận

Chuyên mục Hướng dẫn

Tổng hợp các bài viết hướng dẫn, nghiên cứu và phân tích chi tiết về kỹ thuật, các xu hướng công nghệ mới nhất dành cho lập trình viên.

Đăng ký nhận bản tin của chúng tôi

Hãy trở thành người nhận được các nội dung hữu ích của CyStack sớm nhất

Xem chính sách của chúng tôi Chính sách bảo mật.

Đăng ký nhận Newsletter

Nhận các nội dung hữu ích mới nhất