Spring Batch项目报错JobRepository is mandatory,求修改方案
Spring Batch 报错解决:JobRepository is mandatory
作为Spring Batch初学者,参照官方指南开发简单项目时,运行出现JobRepository is mandatory错误,以下是问题代码、报错信息及修改方案:
问题代码
Controller代码
@RestController @RequestMapping("/jobs") public class JobController { @Autowired private JobLauncher jobLauncher; @Autowired private Job job; @Value("${app.version}") private String appVersion; @GetMapping @RequestMapping("/") public Map getStatus() { Map map = new HashMap<String, String>(); map.put("app-version", appVersion); return map; } @PostMapping("/importCustomers") public void importCsvToDBJob() { JobParameters jobParameters = new JobParametersBuilder() .addLong("startAt", System.currentTimeMillis()).toJobParameters(); try { jobLauncher.run(job, jobParameters); } catch (JobExecutionAlreadyRunningException | JobRestartException | JobInstanceAlreadyCompleteException | JobParametersInvalidException e) { e.printStackTrace(); } } }
Job Config配置代码
@Configuration @EnableBatchProcessing @AllArgsConstructor @NoArgsConstructor public class SpringBatchConfig { private CustomerRepository repo; @Bean public FlatFileItemReader<Customer> reader() { FlatFileItemReader<Customer> itemReader = new FlatFileItemReader<>(); itemReader.setResource(new FileSystemResource("src/main/resources/customers.csv")); itemReader.setName("csvReader"); itemReader.setLinesToSkip(1); itemReader.setLineMapper(lineMapper()); return itemReader; } private LineMapper<Customer> lineMapper() { DefaultLineMapper<Customer> lineMapper = new DefaultLineMapper<>(); DelimitedLineTokenizer lineTokenizer = new DelimitedLineTokenizer(); lineTokenizer.setDelimiter(","); lineTokenizer.setStrict(false); lineTokenizer.setNames("id", "firstName", "lastName", "email", "gender", "contactNo", "country", "dob"); BeanWrapperFieldSetMapper<Customer> fieldSetMapper = new BeanWrapperFieldSetMapper<>(); fieldSetMapper.setTargetType(Customer.class); lineMapper.setLineTokenizer(lineTokenizer); lineMapper.setFieldSetMapper(fieldSetMapper); return lineMapper; } @Bean public CustomerProcessor processor() { return new CustomerProcessor(); } @Bean public JdbcBatchItemWriter<Customer> writer(DataSource dataSource) { return new JdbcBatchItemWriterBuilder<Customer>() .itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>()) .sql("INSERT INTO CUSTOMERS_INFO (CUSTOMER_ID, FIRST_NAME, LAST_NAME, EMAIL, GENDER, CONTACT, COUNTRY, DOB) VALUES (:id, :firstName, :lastName, :email, :gender, :contactNo, :country, :dob)") .dataSource(dataSource) .build(); } @Bean public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager, JdbcBatchItemWriter<Customer> writer) { return new StepBuilder("step1") .<Customer, Customer> chunk(10) .reader(reader()) .processor(processor()) .writer(writer) .taskExecutor(taskExecutor()) .build(); } @Bean public Job importCustomers(JobRepository jobRepository, JobCompletionNotificationListener listener, Step step1) { return new JobBuilder("importCustomers") .incrementer(new RunIdIncrementer()) .listener(listener) .flow(step1) .end() .build(); } @Bean public TaskExecutor taskExecutor() { SimpleAsyncTaskExecutor asyncTaskExecutor = new SimpleAsyncTaskExecutor(); asyncTaskExecutor.setConcurrencyLimit(10); return asyncTaskExecutor; } }
完整报错信息
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'jobController': Unsatisfied dependency expressed through field 'job'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'importCustomers' defined in class path resource [com/javatechie/spring/batch/config/SpringBatchConfig.class]: Unsatisfied dependency expressed through method 'importCustomers' parameter 2; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'step1' defined in class path resource [com/javatechie/spring/batch/config/SpringBatchConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.batch.core.Step]: Factory method 'step1' threw exception; nested exception is org.springframework.batch.core.step.builder.StepBuilderException: java.lang.IllegalStateException: JobRepository is mandatory
问题原因
构建Step和Job时,虽然注入了JobRepository和PlatformTransactionManager参数,但未将它们绑定到对应的构建器实例上。Spring Batch要求Step必须关联JobRepository来管理批处理状态,同时需要TransactionManager处理事务;Job也必须关联JobRepository才能正常初始化。
修改方案
1. 修正Step构建方法
在StepBuilder中显式关联JobRepository和TransactionManager,有两种写法:
写法一:构造器传入
@Bean public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager, JdbcBatchItemWriter<Customer> writer) { return new StepBuilder("step1", jobRepository) // 构造器传入JobRepository .<Customer, Customer> chunk(10, transactionManager) // chunk方法传入TransactionManager .reader(reader()) .processor(processor()) .writer(writer) .taskExecutor(taskExecutor()) .build(); }
写法二:调用builder方法绑定
@Bean public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager, JdbcBatchItemWriter<Customer> writer) { return new StepBuilder("step1") .repository(jobRepository) // 绑定JobRepository .transactionManager(transactionManager) // 绑定TransactionManager .<Customer, Customer> chunk(10) .reader(reader()) .processor(processor()) .writer(writer) .taskExecutor(taskExecutor()) .build(); }
2. 修正Job构建方法
在JobBuilder构造器中传入JobRepository:
@Bean public Job importCustomers(JobRepository jobRepository, JobCompletionNotificationListener listener, Step step1) { return new JobBuilder("importCustomers", jobRepository) // 构造器传入JobRepository .incrementer(new RunIdIncrementer()) .listener(listener) .flow(step1) .end() .build(); }
补充说明
@EnableBatchProcessing注解会自动配置JobRepository和PlatformTransactionManager(前提是项目已正确配置数据源),无需手动定义这两个Bean。- 确保项目配置文件(application.properties/yml)中包含正确的数据库连接信息,
JobRepository需要依赖数据源存储批处理元数据。
内容的提问来源于stack exchange,提问作者Satya Priya Biswas
相关产品推荐
相关产品推荐

