Spring Batch 服务:扩展 DefaultBatchConfiguration 时出现 UnsatisfiedDependencyException

问题描述 投票:0回答:1

感谢您帮助查找尝试扩展 DefaultBatchConfiguration 时引发的下面列出的异常的原因。当不扩展“默认批处理配置”时,下面显示的 Spring Batch 服务可以正常工作。我是 Spring Batch 服务的新手,我正在按照链接“https://spring.io/guides/gs/batch-processing#header”中的 spring 教程进行培训,以创建批处理服务。如果来自 StakeOverflow 社区的人解释如何在扩展 DefaultBatchConfiguration 时配置 Spring Batch 服务,这将是一个很大的帮助,目标是解决问题并让我更深入地理解如何扩展默认批处理配置。

实施细节:

  • 使用 SpringBootApplication 来运行作业
  • 使用两个数据库
    • MySQL 作为作业存储库
    • PostgreSQL 作为数据
  • Maven 项目
  • IDE Eclipse

使用的库和版本:

  • Java JDK 版本 22
  • Spring 批处理版本 5.1.2
  • Spring Boot版本5.1.2
  • PostgreSQL 版本 42.7.2
  • MySQL 连接器版本 8.0.33
Debug Log:
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::               (v3.2.10)

2024-11-05T14:30:17.788-05:00  INFO 2912 --- [           main] c.e.b.BatchProcessingApplication         : Starting BatchProcessingApplication using Java 22 with PID 2912 (D:\User\Gilmar\git-repo\spring-batch-mastery\spring-batch-initial\target\classes started by Gilmar in D:\User\Gilmar\git-repo\spring-batch-mastery\spring-batch-initial)
2024-11-05T14:30:17.790-05:00  INFO 2912 --- [           main] c.e.b.BatchProcessingApplication         : No active profile set, falling back to 1 default profile: "default"
2024-11-05T14:30:18.464-05:00  WARN 2912 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'batchConfiguration' of type [com.example.batchprocessing.BatchConfiguration$$SpringCGLIB$$0] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). The currently created BeanPostProcessor [jobRegistryBeanPostProcessor] is declared through a non-static factory method on that class; consider declaring it as static instead.
2024-11-05T14:30:18.488-05:00  WARN 2912 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'jobRegistry' of type [org.springframework.batch.core.configuration.support.MapJobRegistry] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [jobRegistryBeanPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies.
2024-11-05T14:30:18.562-05:00  INFO 2912 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2024-11-05T14:30:19.026-05:00  INFO 2912 --- [           main] com.zaxxer.hikari.pool.HikariPool        : HikariPool-1 - Added connection com.mysql.cj.jdbc.ConnectionImpl@6778aea6
2024-11-05T14:30:19.028-05:00  INFO 2912 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2024-11-05T14:30:19.061-05:00  INFO 2912 --- [           main] c.e.batchprocessing.BatchConfiguration   : ******jobTemplate running******
2024-11-05T14:30:19.078-05:00  INFO 2912 --- [           main] c.e.batchprocessing.BatchConfiguration   : ******FlatFileItemReader******
2024-11-05T14:30:19.095-05:00  INFO 2912 --- [           main] c.e.batchprocessing.BatchConfiguration   : ******PersonItemProcessor******
2024-11-05T14:30:19.096-05:00  INFO 2912 --- [           main] c.e.batchprocessing.BatchConfiguration   : ******JdbcBatchItemWriter******
2024-11-05T14:30:19.118-05:00  INFO 2912 --- [           main] o.s.b.c.r.s.JobRepositoryFactoryBean     : No database type set, using meta data indicating: MYSQL
2024-11-05T14:30:19.145-05:00  WARN 2912 --- [           main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'importUserJob' defined in class path resource [com/example/batchprocessing/BatchConfiguration.class]: Unsatisfied dependency expressed through method 'importUserJob' parameter 1: Error creating bean with name 'step1' defined in class path resource [com/example/batchprocessing/BatchConfiguration.class]: Unsatisfied dependency expressed through method 'step1' parameter 0: Error creating bean with name 'jobRepository' defined in class path resource [com/example/batchprocessing/BatchConfiguration.class]: Failed to instantiate [org.springframework.batch.core.repository.JobRepository]: Factory method 'jobRepository' threw exception with message: Unable to configure the default job repository
2024-11-05T14:30:19.147-05:00  INFO 2912 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2024-11-05T14:30:19.196-05:00  INFO 2912 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.
2024-11-05T14:30:19.220-05:00  INFO 2912 --- [           main] .s.b.a.l.ConditionEvaluationReportLogger : 

Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2024-11-05T14:30:19.249-05:00 ERROR 2912 --- [           main] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'importUserJob' defined in class path resource [com/example/batchprocessing/BatchConfiguration.class]: Unsatisfied dependency expressed through method 'importUserJob' parameter 1: Error creating bean with name 'step1' defined in class path resource [com/example/batchprocessing/BatchConfiguration.class]: Unsatisfied dependency expressed through method 'step1' parameter 0: Error creating bean with name 'jobRepository' defined in class path resource [com/example/batchprocessing/BatchConfiguration.class]: Failed to instantiate [org.springframework.batch.core.repository.JobRepository]: Factory method 'jobRepository' threw exception with message: Unable to configure the default job repository
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:795) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:542) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1355) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1185) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:562) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:971) ~[spring-context-6.1.13.jar:6.1.13]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:625) ~[spring-context-6.1.13.jar:6.1.13]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.2.10.jar:3.2.10]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.2.10.jar:3.2.10]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) ~[spring-boot-3.2.10.jar:3.2.10]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363) ~[spring-boot-3.2.10.jar:3.2.10]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352) ~[spring-boot-3.2.10.jar:3.2.10]
    at com.example.batchprocessing.BatchProcessingApplication.main(BatchProcessingApplication.java:11) ~[classes/:na]
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'step1' defined in class path resource [com/example/batchprocessing/BatchConfiguration.class]: Unsatisfied dependency expressed through method 'step1' parameter 0: Error creating bean with name 'jobRepository' defined in class path resource [com/example/batchprocessing/BatchConfiguration.class]: Failed to instantiate [org.springframework.batch.core.repository.JobRepository]: Factory method 'jobRepository' threw exception with message: Unable to configure the default job repository
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:795) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:542) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1355) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1185) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:562) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1443) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1353) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:904) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:782) ~[spring-beans-6.1.13.jar:6.1.13]
    ... 18 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jobRepository' defined in class path resource [com/example/batchprocessing/BatchConfiguration.class]: Failed to instantiate [org.springframework.batch.core.repository.JobRepository]: Factory method 'jobRepository' threw exception with message: Unable to configure the default job repository
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:648) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:485) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1355) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1185) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:562) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1443) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1353) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:904) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:782) ~[spring-beans-6.1.13.jar:6.1.13]
    ... 32 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.batch.core.repository.JobRepository]: Factory method 'jobRepository' threw exception with message: Unable to configure the default job repository
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:178) ~[spring-beans-6.1.13.jar:6.1.13]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:644) ~[spring-beans-6.1.13.jar:6.1.13]
    ... 46 common frames omitted
Caused by: org.springframework.batch.core.configuration.BatchConfigurationException: Unable to configure the default job repository
    at org.springframework.batch.core.configuration.support.DefaultBatchConfiguration.jobRepository(DefaultBatchConfiguration.java:151) ~[spring-batch-core-5.1.2.jar:5.1.2]
    at com.example.batchprocessing.BatchConfiguration$$SpringCGLIB$$0.CGLIB$jobRepository$29(<generated>) ~[classes/:na]
    at com.example.batchprocessing.BatchConfiguration$$SpringCGLIB$$FastClass$$1.invoke(<generated>) ~[classes/:na]
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:258) ~[spring-core-6.1.13.jar:6.1.13]
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:348) ~[spring-context-6.1.13.jar:6.1.13]
    at com.example.batchprocessing.BatchConfiguration$$SpringCGLIB$$0.jobRepository(<generated>) ~[classes/:na]
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na]
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:146) ~[spring-beans-6.1.13.jar:6.1.13]
    ... 47 common frames omitted
Caused by: org.springframework.batch.core.configuration.BatchConfigurationException:  To use the default configuration, a data source bean named 'dataSource' should be defined in the application context but none was found. Override getDataSource() to provide the data source to use for Batch meta-data.
    at org.springframework.batch.core.configuration.support.DefaultBatchConfiguration.getDataSource(DefaultBatchConfiguration.java:250) ~[spring-batch-core-5.1.2.jar:5.1.2]
    at org.springframework.batch.core.configuration.support.DefaultBatchConfiguration.jobRepository(DefaultBatchConfiguration.java:132) ~[spring-batch-core-5.1.2.jar:5.1.2]
    ... 55 common frames omitted

------代码------

@SpringBootApplication
public class BatchProcessingApplication {
    public static void main(String[] args) {
    System.exit(SpringApplication.exit(SpringApplication.run(BatchProcessingApplication.class, args)));
    }
}
@Configuration
public class BatchConfiguration extends DefaultBatchConfiguration {
//public class BatchConfiguration {
    
    private static final Logger log = LoggerFactory.getLogger(BatchConfiguration.class);
    
    @Bean("jdbcTemplate")
    public JdbcTemplate jdbcTemplate( @Qualifier("pgDataSource")DataSource dataSource) {
        log.info("******jobTemplate running******");
        return new JdbcTemplate(dataSource);
    }
    
    @Bean("reader")
    public FlatFileItemReader<Person> reader() {
        log.info("******FlatFileItemReader******");
      return new FlatFileItemReaderBuilder<Person>()
        .name("personItemReader")
        .resource(new ClassPathResource("sample-data.csv"))
        .delimited()
        .delimiter(",")
        .names("firstName", "lastName")
        .targetType(Person.class)
        .build();
    }
    @Bean("processor")
    public PersonItemProcessor processor() {
      log.info("******PersonItemProcessor******");
      return new PersonItemProcessor();
    }

    @Bean("writer")
    public JdbcBatchItemWriter<Person> writer( @Qualifier("pgDataSource") DataSource dataRepository) {
        log.info("******JdbcBatchItemWriter******");
      return new JdbcBatchItemWriterBuilder<Person>()
        .sql("INSERT INTO people (first_name, last_name) VALUES (:firstName, :lastName)")
        .dataSource(dataRepository)
        .beanMapped()
        .build();
    }
    
    @Bean("importUserJob")
    public Job importUserJob(@Qualifier(
            "mySQLJobRepository")JobRepository jobRepository,
            Step step1,
            JobCompletionNotificationListener listener) {
        
        log.info("******importUserJob******");
        return new JobBuilder("importUserJob", jobRepository)
            .listener(listener)
            .start(step1)
            .build();
    }
    @Bean("step1")
    public Step step1(JobRepository jobRepository,  
            DataSourceTransactionManager transactionManager,
            @Qualifier("reader")FlatFileItemReader<Person> reader,
            @Qualifier("processor")PersonItemProcessor processor,
            @Qualifier("writer")JdbcBatchItemWriter<Person> writer) {
        
        log.info("******step1******");
        return new StepBuilder("step1", jobRepository)
        .<Person, Person> chunk(3, transactionManager)
        .reader(reader)
        .processor(processor)
        .writer(writer)
        .build();
    }
    
    /***** Spring Batch Data sources and Job Repository*****/
    /**
     * This method created a Job repository 
     * @param mySQLDataSource contains the dataSource object to create a Job Repository
     * @return
     * @throws Exception
     */
    @Bean("mySQLJobRepository")
    public JobRepository jobRepository(DataSource mySQLDataSource) throws Exception {
    
        JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
        factory.setDataSource(mySQLDataSource);
        factory.setTransactionManager(new DataSourceTransactionManager(mySQLDataSource));
        factory.setIsolationLevelForCreate("ISOLATION_SERIALIZABLE");
        factory.setMaxVarCharLength(255);
        factory.afterPropertiesSet();
        
        return factory.getObject();
    }
    /**
     * This method creates a data source based on properties settings in the   *"application.properties" to manage the MySQL database to use as the Job Repository.
     * 
     * @return a data source object
     * 
     * Note:
     *    The @ConfigurationProperty @Value annotations are redundant for training purposes, just one is good enough.
     */
    @Primary
    @Bean("mySQLDataSource")
    @ConfigurationProperties(prefix = "db.job.repo")
    public DataSource mySQLDataSource(
            @Value("${db.job.repo.driverClassName}") String className,
            @Value("${db.job.repo.jdbc-url}") String url,
            @Value("${db.job.repo.username}") String userName,
            @Value("${db.job.repo.schema}") String password) {
        return DataSourceBuilder
                .create()
                .driverClassName(className)
                .url(url)
                .username(userName)
                .password(password)
                .build();
    }
        
    /**
     * This method creates a data source based on the properties settings in the "application.properties" to manage the PostgreSQL database to use as data repository.
     * @return dataSource object created
     * 
     * Note:
     *    The @ConfigurationProperty @Value annotations are redundant for training purposes, just one is good enough.  
     */
    @Bean("pgDataSource")
    @ConfigurationProperties(prefix = "db.src")
    public DataSource pgDataRepository(
            @Value("${db.src.driverClassName}") String className,
            @Value("${db.src.jdbc-url}") String url, 
            @Value("${db.src.username}") String userName,
            @Value("${db.src.password}") String password) {
        
        return DataSourceBuilder
                .create()
                .driverClassName(className)
                .url(url).username(userName)
                .password(password)
                .build();
    }
}
@Component
public class JobCompletionNotificationListener implements JobExecutionListener {

    private static final Logger log = LoggerFactory.getLogger(JobCompletionNotificationListener.class);

    private final JdbcTemplate jdbcTemplate;
    
    /**
     * Constructor - It will allows to create an object/instance of JdbcTemplate because spring data jdbc on on the JAVA Library path
     * @param jdbcTemplate
     */
    public JobCompletionNotificationListener(JdbcTemplate jdbcTemplate) {
            this.jdbcTemplate = jdbcTemplate;
          }

    @Override
    public void beforeJob(JobExecution jobExecution) {
        JobExecutionListener.super.beforeJob(jobExecution);
        log.info("Job {} started", jobExecution.getJobInstance().getJobName());
    }

    @Override
    public void afterJob(JobExecution jobExecution) {
        JobExecutionListener.super.afterJob(jobExecution);
        log.info("Job {} end", jobExecution.getJobInstance().getJobName());
        if (jobExecution.getStatus() == BatchStatus.COMPLETED) {
            log.info("!!! JOB FINISHED! Time to verify the results");

            jdbcTemplate.query("SELECT first_name, last_name FROM people", new DataClassRowMapper<>(Person.class))
                    .forEach(person -> log.info("Found - first name, last name ( {},{}) in the database.", person.firstName(),person.lastName() ));
        }
    }
}
public record Person(String firstName, String lastName) {}
public class PersonItemProcessor implements ItemProcessor<Person, Person> {

    private static final Logger log = LoggerFactory.getLogger(PersonItemProcessor.class);
    
    @Override
    public Person process(final Person person) {
        final String firstName = person.firstName().toUpperCase();
        final String lastName = person.lastName().toUpperCase();
        
        final Person transformedPerson = new Person(firstName, lastName);
        
        log.info("Converting (" + person + ") into (" + transformedPerson + ")");

        return transformedPerson;
    }
}

src/主/资源

***application.properties***

db.job.repo.driverClassName=com.mysql.cj.jdbc.Driver
db.job.repo.jdbc-url=jdbc:mysql://localhost:3306/batch-initial?currentSchema=batch-initial
db.job.repo.username=****
db.job.repo.password=*****
db.job.repo.schema=batch-initial
# Whether to populate schema for Spring Batch in case it's absent
#batch.db.initialize-schema=ALWAYS
db.job.repo.initialize-schema=ALWAYS

db.src.jdbc-url=jdbc:postgresql://127.0.0.1:5432/SPRINGBATCH?currentSchema=batch-initial
db.src.username=******
db.src.password=******
db.src.driverClassName=org.postgresql.Driver
***data.sql***

DROP TABLE people IF EXISTS;

CREATE TABLE people  (
 --   id BIGINT AUTO_INCREMENT PRIMARY KEY,
    person_id BIGINT AUTO_INCREMENT NOT NULL PRIMARY KEY,
    first_name VARCHAR(20),
    last_name VARCHAR(20)
);
***sample-data.txt***

Jill,Doe
Joe,Doe
Justin,Doe
Jane,Doe
John,Doe

文件

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.10</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>batchprocessing</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Batch Service</description>
    <url/>
    <licenses>
        <license/>
    </licenses>
    <developers>
        <developer/>
    </developers>
    <scm>
        <connection/>
        <developerConnection/>
        <tag/>
        <url/>
    </scm>
    <properties>
        <java.version>22</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-batch</artifactId>
        </dependency>
                <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.postgresql/postgresql -->
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>42.7.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.batch</groupId>
            <artifactId>spring-batch-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

我希望在配置 Spring Batch 服务时扩展

DefauldBatchConfiguration

spring spring-boot spring-data spring-batch multiple-databases
1个回答
0
投票

引起:org.springframework.batch.core.configuration.BatchConfigurationException:要使用默认配置,应在应用程序上下文中定义一个名为“dataSource”的数据源bean,但没有找到。重写 getDataSource() 以提供用于批处理元数据的数据源。

正如此错误消息所解释的,您需要定义一个名为“dataSource”的数据源,或覆盖

DefaultBatchConfiguration#getDataSource()
以提供用于批处理元数据的数据源。

© www.soinside.com 2019 - 2024. All rights reserved.