SoFunction
Updated on 2025-04-14

Implementation of SpringBatch data reading (ItemReader and custom read logic)

introduction

Data reading is a key link in the batch process, which directly affects the performance and stability of batch tasks. Spring Batch provides a powerful data reading mechanism, which enables developers to easily read data from various data sources through the ItemReader interface and its rich implementation. This article will explore the ItemReader system in Spring Batch, including built-in implementation, custom read logic and performance optimization techniques, to help developers master efficient data reading methods and build reliable batch applications.

1. ItemReader core concept

ItemReader is the core interface responsible for data reading in Spring Batch, and defines a standard method for reading data item by item from a data source. It uses iterator mode, and returns a data item each time the read() method is called until null is returned to indicate that the data has been read. This design allows Spring Batch to effectively control the pace of data processing, implement chunk processing, and submit transactions at the appropriate time.

Spring Batch closely combines ItemReader with transaction management to ensure that exceptions during data reading can be handled correctly and supports job restart and recovery. For stateful ItemReader, Spring Batch provides an ItemStream interface to manage read state and support continuing execution from a breakpoint when a job restarts.

import ;
import ;
import ;

// ItemReader core interfacepublic interface ItemReader<T> {
    /**
      * Read a data item
      * Return to null to indicate the end of the read
      */
    T read() throws Exception;
}

// ItemStream interface is used to manage read statepublic interface ItemStream {
    /**
      * Open the resource and initialize the status
      */
    void open(ExecutionContext executionContext) throws ItemStreamException;
    
    /**
      * Update status information in execution context
      */
    void update(ExecutionContext executionContext) throws ItemStreamException;
    
    /**
      * Close resources and clean up state
      */
    void close() throws ItemStreamException;
}

2. File data reading

Files are one of the most common data sources in batch processing, and Spring Batch provides a variety of ItemReader implementations for reading files. FlatFileItemReader is suitable for reading structured text files, such as delimiter-delimited files such as CSV and TSV; JsonItemReader and XmlItemReader are used to read files in JSON and XML formats respectively.

For large file processing, Spring Batch's file reader supports restart and skip policies, which can continue reading from the last processed location, avoiding repeated processing of processed data. The key to optimizing file read performance lies in the rational setting of buffer size, delayed loading and resource management.

// CSV file reader@Bean
public FlatFileItemReader<Transaction> csvTransactionReader() {
    FlatFileItemReader<Transaction> reader = new FlatFileItemReader<>();
    (new FileSystemResource("data/"));
    (1); // Skip the title line    
    // Configure the row mapper    DefaultLineMapper<Transaction> lineMapper = new DefaultLineMapper<>();
    
    // Configure the separator parser    DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer();
    (",");
    ("id", "date", "amount", "customerId", "type");
    (tokenizer);
    
    // Configure the field mapper    BeanWrapperFieldSetMapper<Transaction> fieldSetMapper = new BeanWrapperFieldSetMapper<>();
    ();
    (fieldSetMapper);
    
    (lineMapper);
    ("transactionItemReader");
    
    return reader;
}

3. Database data reading

Databases are the most commonly used data storage method for enterprise applications, and Spring Batch provides rich database reading support. JdbcCursorItemReader uses the traditional JDBC cursor method to read data line by line; JdbcPagingItemReader uses paging to load data, which is suitable for processing large data volumes; HibernateCursorItemReader and JpaPagingItemReader provide data reading implementations based on Hibernate and JPA respectively.

When designing database reading, you need to weigh performance and resource consumption. The cursor method keeps the database connection until the reading is completed, which is suitable for small batches of data; the pagination method loads part of the data every time the query is query, which is suitable for large batches of data. Properly setting batch sizes and query conditions can significantly improve performance.

// JDBC paging reader@Bean
public JdbcPagingItemReader<Order> jdbcPagingReader(DataSource dataSource) throws Exception {
    JdbcPagingItemReader<Order> reader = new JdbcPagingItemReader<>();
    (dataSource);
    (100); // Set page size    (100);
    
    // Configure query parameters    Map<String, Object> parameterValues = new HashMap<>();
    ("status", "PENDING");
    (parameterValues);
    
    // Configure the row mapper    (new OrderRowMapper());
    
    // Configure the pagination query provider    SqlPagingQueryProviderFactoryBean queryProviderFactory = new SqlPagingQueryProviderFactoryBean();
    (dataSource);
    ("SELECT id, customer_id, order_date, total_amount, status");
    ("FROM orders");
    ("WHERE status = :status");
    ("id");
    
    (());
    
    return reader;
}

4. Multi-source data reading

In practical applications, batch tasks may require reading data from multiple data sources and integrating them. Spring Batch provides MultiResourceItemReader for reading multiple resource files, CompositeItemReader is used to combine multiple ItemReader, and custom ItemReader can implement more complex multi-source data reading logic.

When designing multi-source data reading, you need to consider the data association method, reading order and error handling strategy. Effective data integration can reduce unnecessary processing steps and improve batch processing efficiency.

// Multi-resource file reader@Bean
public MultiResourceItemReader<Customer> multiResourceReader() throws IOException {
    MultiResourceItemReader<Customer> multiReader = new MultiResourceItemReader<>();
    
    // Get multiple resource files    Resource[] resources = new PathMatchingResourcePatternResolver()
            .getResources("classpath:data/customers_*.csv");
    (resources);
    
    // Set up a delegate reader    FlatFileItemReader<Customer> delegateReader = new FlatFileItemReader<>();
    // Configure the delegate reader...    (delegateReader);
    
    return multiReader;
}

5. Customize ItemReader implementation

Although Spring Batch provides a rich built-in ItemReader implementation, it may be necessary to develop a custom ItemReader in specific business scenarios. Custom ItemReader usually needs to handle details such as data source connection, state management, exception handling, etc. to ensure normal operation in the batch environment.

When developing a custom ItemReader, you should follow the design principles of Spring Batch to implement the ItemReader interface to provide data reading capabilities, and if necessary, implement the ItemStream interface to support state management. Good custom implementations should consider performance optimization, resource management, and error recovery.

// REST API data reader@Component
public class RestApiItemReader<T> implements ItemReader<T>, ItemStream {
    
    private final RestTemplate restTemplate;
    private final String apiUrl;
    private final Class<T> targetType;
    
    private int currentPage = 0;
    private int pageSize = 100;
    private List<T> currentItems;
    private int currentIndex;
    private boolean exhausted = false;
    
    // Status Save Key    private static final String CURRENT_PAGE_KEY = "";
    private String name;
    
    public RestApiItemReader(RestTemplate restTemplate, String apiUrl, Class<T> targetType) {
         = restTemplate;
         = apiUrl;
         = targetType;
    }
    
    @Override
    public T read() throws Exception {
        // If the current batch data is empty or has been read, load the next batch        if (currentItems == null || currentIndex >= ()) {
            if (exhausted) {
                return null; // All data has been read            }
            
            fetchNextBatch();
            
            // If the list is empty after loading, it means that all data has been read.            if (()) {
                exhausted = true;
                return null;
            }
            
            currentIndex = 0;
        }
        
        return (currentIndex++);
    }
    
    private void fetchNextBatch() {
        String url = apiUrl + "?page=" + currentPage + "&size=" + pageSize;
        ResponseEntity<ApiResponse<T>> response = (
                url, (Class<ApiResponse<T>>) );
        
        ApiResponse<T> apiResponse = ();
        currentItems = ();
        exhausted = ();
        currentPage++;
    }
    
    // The ItemStream interface implementation is omitted...}

6. Read performance optimization strategy

When processing large-data batch tasks, the performance of ItemReader will directly affect the execution efficiency of the entire job. Performance optimization strategies include setting the appropriate batch size, using paging or sharding technology, implementing parallel reading, using lazy loading, and optimizing resource usage.

Optimization strategies vary for different types of data sources. For file reading, the buffer size can be adjusted and efficient parsers can be used; for database reading, SQL queries can be optimized, indexes can be used and resized. For remote API calls, caching mechanisms and batch requests can be implemented.

// Data partitioning policy@Component
public class RangePartitioner implements Partitioner {
    
    @Override
    public Map<String, ExecutionContext> partition(int gridSize) {
        Map<String, ExecutionContext> partitions = new HashMap<>(gridSize);
        
        // Get the total number of data        long totalRecords = getTotalRecords();
        long targetSize = totalRecords / gridSize + 1;
        
        // Create partition        for (int i = 0; i < gridSize; i++) {
            ExecutionContext context = new ExecutionContext();
            
            long fromId = i * targetSize + 1;
            long toId = (i + 1) * targetSize;
            if (toId > totalRecords) {
                toId = totalRecords;
            }
            
            ("fromId", fromId);
            ("toId", toId);
            
            ("partition-" + i, context);
        }
        
        return partitions;
    }
    
    private long getTotalRecords() {
        // Implementation of obtaining the total number of data        return 1000000;
    }
}

7. Read state management and error handling

During batch processing, you may encounter data read errors or job interruptions. Spring Batch provides a complete state management and error handling mechanism, saves and restores read state through ExecutionContext, and supports job restart and recovery. ItemReader implementations usually require tracking the current read location and updating the ExecutionContext at the appropriate time.

Error handling strategies include skipping, retrying and error recording, and you can choose the appropriate strategy based on business needs. Good error handling capabilities can improve the reliability and resilience of batch tasks and ensure normal operation in the face of abnormal situations.

//Configuration error handling and state management@Bean
public Step robustStep(
        ItemReader<InputData> reader,
        ItemProcessor<InputData, OutputData> processor,
        ItemWriter<OutputData> writer,
        SkipPolicy skipPolicy) {
    
    return ("robustStep")
            .<InputData, OutputData>chunk(100)
            .reader(reader)
            .processor(processor)
            .writer(writer)
            // Configuration error handling            .faultTolerant()
            .skipPolicy(skipPolicy)
            .retryLimit(3)
            .retry()
            .noRetry()
            .listener(new ItemReadListener<InputData>() {
                @Override
                public void onReadError(Exception ex) {
                    // Record read error                    logError("Read error", ex);
                }
            })
            .build();
}

Summarize

Spring Batch's ItemReader system provides powerful and flexible data reading capabilities for batch applications. By understanding the core concepts and built-in implementation of ItemReader, mastering the development methods of custom ItemReader, as well as application performance optimization and error handling strategies, developers can build efficient and reliable batch applications. In actual applications, appropriate ItemReader implementation or develop custom implementations based on data source characteristics and business needs should be selected to improve the performance and reliability of batch tasks through reasonable configuration and optimization. Whether it is processing files, databases, or API data, Spring Batch provides complete solutions to make enterprise-level batch application development simple and efficient.

This is the end of this article about the implementation of SpringBatch data reading (ItemReader and custom reading logic). For more related Spring Batch data reading content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!