JdbcPagingItemReader配置Step时因NamedParameterJdbcTemplate为空报错
Spring Batch JdbcPagingItemReader 空指针问题排查
问题描述
我正尝试创建一个Spring Batch步骤,该步骤读取ProductDetail信息,经处理器生成新的ProductResult并写入MongoDB数据库。使用JdbcPagingItemReader从数据库读取数据时,启动作业抛出以下错误:
java.lang.NullPointerException: Cannot invoke "org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.getJdbcOperations()" because "this.namedParameterJdbcTemplate" is null.
更换其他Reader可正常运行,仅JdbcPagingItemReader存在问题。已配置查询语句和行映射器,不解为何需要NamedParameterJdbcTemplate,附上配置代码,请问遗漏了什么?
import com.datacom.mapper.ProductDetailRowMapper; import com.datacom.model.ProductDetail; import lombok.RequiredArgsConstructor; import org.springframework.batch.core.Step; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; import org.springframework.batch.item.ItemStreamReader; import org.springframework.batch.item.ItemWriter; import org.springframework.batch.item.data.MongoItemWriter; import org.springframework.batch.item.data.builder.MongoItemWriterBuilder; import org.springframework.batch.item.database.JdbcPagingItemReader; import org.springframework.batch.item.database.Order; import org.springframework.batch.item.database.support.OraclePagingQueryProvider; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.transaction.PlatformTransactionManager; import javax.sql.DataSource; import java.util.HashMap; import java.util.Map; @Configuration @RequiredArgsConstructor public class ProductDetailConfigStep { @Value("${db.pageSize}") int pageSize; final MongoOperations mongoOperations; final @Qualifier("productsDataSource") DataSource dataSource; final PlatformTransactionManager transactionManager; final JobRepository jobRepository; @Value("${batch.chunkSize}") int chunkSize; final ProductResultProcessor productResultProcessor; public ItemStreamReader<ProductDetail> itemReader() { JdbcPagingItemReader<ProductDetail> itemReader = new JdbcPagingItemReader<>(); itemReader.setDataSource(productsDataSource); itemReader.setFetchSize(chunkSize); OraclePagingQueryProvider queryProvider = new OraclePagingQueryProvider(); queryProvider.setSelectClause(JDBCConstants.SELECT_QUERY); queryProvider.setFromClause(JDBCConstants.FROM_CLAUSE_QUERY); itemReader.setRowMapper(new ProductDetailRowMapper()); final Map<String, Order> sortKeys = new HashMap<>(); itemReader.setParameterValues(new HashMap<>()); sortKeys.put("product_id", Order.ASCENDING); queryProvider.setSortKeys(sortKeys); itemReader.setQueryProvider(queryProvider); itemReader.setPageSize(pageSize); itemReader.setPageSize(chunkSize); return itemReader; } public ItemWriter<ProductResult> itemWriter() { var writer = new MongoItemWriterBuilder<ProductResult>() .collection(Documents.PRODUCT_CATALOG_COLLECTION) .mode(MongoItemWriter.Mode.INSERT) .template(mongoOperations) .build(); writer.setTemplate(mongoOperations); return writer; } @Bean("productProcessingDetailStep") public Step productProcessingDetailStep() { return new StepBuilder("productCreationStep", jobRepository) .<ProductDetail, ProductResult>chunk(chunkSize, transactionManager) .reader(itemReader()) .processor(productResultProcessor) .writer(itemWriter()) .build(); } }
问题根源
代码里有两个关键错误导致空指针:
- 数据源引用错误:
itemReader()方法中调用了itemReader.setDataSource(productsDataSource);,但类中注入的数据源变量名是dataSource(带有@Qualifier("productsDataSource")注解),这里的productsDataSource是未定义变量,导致数据源未正确设置,进而使NamedParameterJdbcTemplate无法初始化。 - 重复设置pageSize:连续调用
itemReader.setPageSize(pageSize);和itemReader.setPageSize(chunkSize);,虽不是空指针直接原因,但会覆盖分页大小,建议只保留一个合理设置。
修复后的代码
修改itemReader()方法,修正数据源引用并移除重复的pageSize设置:
public ItemStreamReader<ProductDetail> itemReader() { JdbcPagingItemReader<ProductDetail> itemReader = new JdbcPagingItemReader<>(); // 修正为注入的dataSource变量 itemReader.setDataSource(dataSource); itemReader.setFetchSize(chunkSize); OraclePagingQueryProvider queryProvider = new OraclePagingQueryProvider(); queryProvider.setSelectClause(JDBCConstants.SELECT_QUERY); queryProvider.setFromClause(JDBCConstants.FROM_CLAUSE_QUERY); itemReader.setRowMapper(new ProductDetailRowMapper()); final Map<String, Order> sortKeys = new HashMap<>(); itemReader.setParameterValues(new HashMap<>()); sortKeys.put("product_id", Order.ASCENDING); queryProvider.setSortKeys(sortKeys); itemReader.setQueryProvider(queryProvider); // 只保留一个pageSize设置,根据需求选择pageSize或chunkSize itemReader.setPageSize(pageSize); return itemReader; }
补充说明
JdbcPagingItemReader内部依赖NamedParameterJdbcTemplate执行分页查询,而NamedParameterJdbcTemplate需要通过设置的DataSource初始化。当错误传入未定义的数据源变量时,Reader内部数据源为null,导致NamedParameterJdbcTemplate无法实例化,最终抛出空指针异常。
内容的提问来源于stack exchange,提问作者BreenDeen
相关产品推荐
相关产品推荐

