java
63 lines · 9 steps
How a chunk-based CSV import job works in Spring
A Spring Batch job reads customers from CSV, cleans each record, and writes them to the database in fault-tolerant chunks.
Explained by
highlit
1@Configuration
2@EnableBatchProcessing
3public class CustomerImportJobConfig {
4
5 @Bean
6 public FlatFileItemReader<CustomerCsvRecord> customerReader() {
7 return new FlatFileItemReaderBuilder<CustomerCsvRecord>()
8 .name("customerReader")
9 .resource(new ClassPathResource("customers.csv"))
10 .linesToSkip(1)
11 .delimited()
12 .names("externalId", "firstName", "lastName", "email", "signupDate")
13 .fieldSetMapper(fieldSet -> new CustomerCsvRecord(
14 fieldSet.readString("externalId"),
15 fieldSet.readString("firstName"),
16 fieldSet.readString("lastName"),
17 fieldSet.readString("email"),
18 fieldSet.readDate("signupDate", "yyyy-MM-dd")))
19 .build();
20 }
21
22 @Bean
23 public ItemProcessor<CustomerCsvRecord, Customer> customerProcessor() {
24 return record -> {
25 if (record.email() == null || record.email().isBlank()) {
26 return null;
27 }
28 Customer customer = new Customer();
29 customer.setExternalId(record.externalId());
30 customer.setName(record.firstName().trim() + " " + record.lastName().trim());
31 customer.setEmail(record.email().toLowerCase());
32 customer.setSignupDate(record.signupDate());
33 return customer;
34 };
35 }
36
37 @Bean
38 public JdbcBatchItemWriter<Customer> customerWriter(DataSource dataSource) {
39 return new JdbcBatchItemWriterBuilder<Customer>()
40 .dataSource(dataSource)
41 .sql("INSERT INTO customers (external_id, name, email, signup_date) "
42 + "VALUES (:externalId, :name, :email, :signupDate)")
43 .beanMapped()
44 .build();
45 }
46
47 @Bean
48 public Step importCustomersStep(JobRepository jobRepository,
49 PlatformTransactionManager txManager,
50 FlatFileItemReader<CustomerCsvRecord> customerReader,
51 ItemProcessor<CustomerCsvRecord, Customer> customerProcessor,
52 JdbcBatchItemWriter<Customer> customerWriter) {
53 return new StepBuilder("importCustomersStep", jobRepository)
54 .<CustomerCsvRecord, Customer>chunk(200, txManager)
55 .reader(customerReader)
56 .processor(customerProcessor)
57 .writer(customerWriter)
58 .faultTolerant()
59 .skip(FlatFileParseException.class)
60 .skipLimit(25)
61 .build();
62 }
63}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Spring Batch's reader-processor-writer triad cleanly separates parsing, transformation, and persistence into swappable beans.
- 2Chunk-oriented steps commit work in fixed-size batches inside a transaction, balancing throughput against memory and rollback scope.
- 3A processor returning null filters an item out, and fault tolerance lets bad rows be skipped without aborting the whole job.
Related explainers
java
@Component @Converter public class EncryptedStringConverter implements AttributeConverter<String, String> {
Transparent column encryption in Spring & JPA
encryption
aes-gcm
jpa-converter
Advanced
10 steps
java
package com.acme.billing.config; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.ConfigurationProperties;
Feature-flagged beans with Spring @ConditionalOnProperty
feature-flags
conditional-beans
strategy-pattern
Intermediate
5 steps
java
public static Map<String, String> parseCookieHeader(String header) { Map<String, String> cookies = new LinkedHashMap<>(); if (header == null || header.isBlank()) { return cookies;
Parsing an HTTP Cookie header in Java
string-parsing
http
url-decoding
Intermediate
6 steps
java
public class TimedSocketReader { private static final int READ_TIMEOUT_MS = 5_000; private static final int CONNECT_TIMEOUT_MS = 3_000;
Reading a socket with connect and read timeouts
sockets
timeouts
io
Intermediate
8 steps
java
public final class EncodingDetector { public enum Encoding { UTF_8, UTF_16LE, UTF_16BE, UTF_32LE, UTF_32BE, ASCII, UNKNOWN
Detecting text encoding from raw bytes in Java
byte-manipulation
encoding-detection
bitwise-operations
Intermediate
8 steps
java
public final class ImportOrganizer { private static final Pattern IMPORT_LINE = Pattern.compile("^import\\s+(static\\s+)?([\\w.]+(?:\\.\\*)?)\\s*;\\s*$");
Sorting Java imports with a regex pass
regex
sorting
text-processing
Intermediate
8 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/how-a-chunk-based-csv-import-job-works-in-spring-explained-java-4601/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.