Ultra barebones Spring Batch project demonstrating different JDBC reading strategies with comprehensive metrics collection.
-
Three Reader Configurations:
JdbcPagingItemReader- Oracle-style paginationJdbcCursorItemReader- Cursor-based reading- Multithreaded
JdbcPagingItemReader- Parallel processing
-
Comprehensive Metrics:
- Total job execution time
- Per-page processing duration
- Page boundary tracking
- Chunk boundary logging
- Average time per record
- Throughput (records/second)
src/main/java/com/example/demo/
├── config/
│ ├── PagingJobConfig.java # Pagination reader config
│ ├── CursorJobConfig.java # Cursor reader config
│ └── MultiThreadPagingJobConfig.java # Multithreaded config
├── listener/
│ ├── MetricsJobExecutionListener.java
│ ├── MetricsItemReadListener.java
│ └── MetricsChunkListener.java
├── metrics/
│ └── BatchMetricsService.java # Metrics tracking & reporting
├── model/
│ └── SampleRecord.java # Domain model
├── processor/
│ └── SampleItemProcessor.java # Item processor
├── writer/
│ └── SampleItemWriter.java # Item writer
└── DemoApplication.java # Main app with CLI runner
- Java 17 or higher
- Maven 3.6+
| Parameter | Description | Default | Applies To |
|---|---|---|---|
pageSize=N |
Page size for paging readers | 10 | paging, multithread |
fetchSize=N |
JDBC fetch size for cursor | 10 | cursor |
maxRows=N |
Maximum records to process | unlimited | all jobs |
threadPoolSize=N |
Thread pool size | 4 | multithread |
Note: Chunk size is configured in application.properties (batch.chunk.size=10)
Basic:
mvn spring-boot:run -Dspring-boot.run.arguments="paging"Custom page size:
mvn spring-boot:run -Dspring-boot.run.arguments="paging pageSize=20"Limit to 25 records:
mvn spring-boot:run -Dspring-boot.run.arguments="paging maxRows=25"Combined:
mvn spring-boot:run -Dspring-boot.run.arguments="paging pageSize=50 maxRows=100"Basic:
mvn spring-boot:run -Dspring-boot.run.arguments="cursor"Custom fetch size:
mvn spring-boot:run -Dspring-boot.run.arguments="cursor fetchSize=15"Process only first 30 records:
mvn spring-boot:run -Dspring-boot.run.arguments="cursor fetchSize=15 maxRows=30"Basic:
mvn spring-boot:run -Dspring-boot.run.arguments="multithread"8 threads with custom page size:
mvn spring-boot:run -Dspring-boot.run.arguments="multithread threadPoolSize=8 pageSize=25"Full control:
mvn spring-boot:run -Dspring-boot.run.arguments="multithread pageSize=20 threadPoolSize=6 maxRows=100"Edit application.properties to customize defaults (can be overridden via command-line):
# Chunk size (number of items processed per transaction)
batch.chunk.size=10
# Page size (for pagination readers)
batch.page.size=100
# Thread pool size (for multithreaded execution)
batch.thread.pool.size=4Chunk size defines the transaction boundary in Spring Batch:
┌─────────────────────────────────────────┐
│ START TRANSACTION │
│ 1. READ chunkSize items │
│ 2. PROCESS each item │
│ 3. WRITE all items at once │
│ COMMIT TRANSACTION │
└─────────────────────────────────────────┘
Repeat...
Example with chunkSize=10 and pageSize=100:
- Database fetches 100 records (1 page)
- Process them in 10 chunks of 10 records each
- Each chunk = 1 transaction/commit
Relationship:
chunkSize≤pageSize: Multiple chunks per pagechunkSize>pageSize: Page fetches happen within a chunkmaxRows: Stops processing after N records total
Tuning:
- Smaller chunks: More commits, better restart capability, slower
- Larger chunks: Fewer commits, faster, more memory, bigger rollback on failure
The project automatically initializes an H2 in-memory database with 50 sample records via schema.sql and data.sql.
Table structure:
CREATE TABLE sample_data (
id BIGINT PRIMARY KEY,
name VARCHAR(100),
value DECIMAL(10, 2),
status VARCHAR(50),
created_date TIMESTAMP
);After job completion, a detailed metrics report is printed:
================================================================================
BATCH JOB METRICS REPORT: pagingJob
================================================================================
Start Time: 2025-10-21T15:30:00
End Time: 2025-10-21T15:30:05
Total Duration: 5000ms (5.0 seconds)
Total Records: 50
Total Pages: 5
--- PAGE METRICS ---
Page 1: 10 records, 950ms
Page 2: 10 records, 980ms
Page 3: 10 records, 1020ms
Page 4: 10 records, 1000ms
Page 5: 10 records, 1050ms
Average Page Duration: 1000.00ms
Average Time Per Record: 100.00ms
Throughput: 10.00 records/second
================================================================================
| Reader Type | Use Case | Pros | Cons |
|---|---|---|---|
| Paging | Large datasets, Oracle DB | Memory efficient, restartable | Multiple queries |
| Cursor | Streaming data | Single query, simple | Holds DB connection |
| Multithreaded | Performance critical | Parallel processing | Higher resource usage |
To use with Oracle instead of H2:
- Update
application.properties:
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:ORCL
spring.datasource.username=your_username
spring.datasource.password=your_password
spring.datasource.driverClassName=oracle.jdbc.OracleDriver- The
OraclePagingQueryProvideris already configured in the paging readers.
DEBUG: Chunk processing, page detailsTRACE: Individual record processingINFO: Job lifecycle, metrics reports
Adjust in application.properties:
logging.level.com.example.demo=DEBUG- Spring Boot 3.5.6
- Spring Batch
- Spring JDBC
- H2 Database (runtime)
- Oracle JDBC Driver (runtime)
- Lombok
- Micrometer (metrics)
MIT