要使用默认的 BatchConfigurer,上下文必须包含不超过一个 DataSource,找到 2
Posted
技术标签:
【中文标题】要使用默认的 BatchConfigurer,上下文必须包含不超过一个 DataSource,找到 2【英文标题】:To use the default BatchConfigurer the context must contain no more thanone DataSource, found 2 【发布时间】:2017-10-29 09:14:17 【问题描述】:我正在使用弹簧靴和弹簧批处理。对于元表,我想使用 mysql,对于所有业务,我想使用 db2 作为数据库。当我实现获取错误时。
application.properties
spring.datasource.url = jdbc:mysql://localhost:3306/local
spring.datasource.username = root
spring.datasource.password = root
spring.jpa.show-sql = true
spring.jpa.hibernate.ddl-auto = update
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
spring.seconddatasource.url=jdbc:db2://***************
spring.seconddatasource.username=******
spring.seconddatasource.password=****
spring.seconddatasource.driverClassName=com.ibm.db2.jcc.DB2Driver
BatchCongig.java
@Configuration
@EnableBatchProcessing
public class BatchConfiguration
@Autowired
public JobBuilderFactory jobBuilderFactory;
@Autowired
public StepBuilderFactory stepBuilderFactory;
@Autowired
public DataSource dataSourceSecond;
@Bean
@ConfigurationProperties(prefix="spring.seconddatasource")
public javax.sql.DataSource secondaryDataSource()
return DataSourceBuilder.create().build();
@Bean
@Primary
@ConfigurationProperties(prefix="spring.datasource")
public javax.sql.DataSource primaryDataSource()
return DataSourceBuilder.create().build();
@Bean
public JdbcCursorItemReader<User> reader()
JdbcCursorItemReader<User> reader=new JdbcCursorItemReader<>();
reader.setDataSource(dataSourceSecond);
reader.setSql("Select ACCT_ID from ACCT_table FETCH FIRST 100 ROWS ONLY");
reader.setRowMapper(new UserRowerMapper());
return reader;
@Bean
public UserItemProcessor processor()
return new UserItemProcessor();
@Bean
public Step step1()
return stepBuilderFactory.get("step1").<User,User>chunk(10)
.reader(reader())
.processor(processor())
.build();
@Bean
public Job job1()
return jobBuilderFactory.get("jobakjkkj")
.incrementer(new RunIdIncrementer())
.flow(step1())
.end()
.build();
错误堆栈
java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:779) [spring-boot-1.5.3.RELEASE.jar:1.5.3.RELEASE]
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:760) [spring-boot-1.5.3.RELEASE.jar:1.5.3.RELEASE]
at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:747) [spring-boot-1.5.3.RELEASE.jar:1.5.3.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-1.5.3.RELEASE.jar:1.5.3.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162) [spring-boot-1.5.3.RELEASE.jar:1.5.3.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151) [spring-boot-1.5.3.RELEASE.jar:1.5.3.RELEASE]
at com.schwab.cat.SpringBatchDbReadApplication.main(SpringBatchDbReadApplication.java:10) [classes/:na]
Caused by: java.lang.IllegalStateException: To use the default BatchConfigurer the context must contain no more thanone DataSource, found 2
at org.springframework.batch.core.configuration.annotation.AbstractBatchConfiguration.getConfigurer(AbstractBatchConfiguration.java:108) ~[spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration.initialize(SimpleBatchConfiguration.java:114) ~[spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$ReferenceTargetSource.createObject(SimpleBatchConfiguration.java:142) ~[spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.aop.target.AbstractLazyCreationTargetSource.getTarget(AbstractLazyCreationTargetSource.java:86) ~[spring-aop-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:192) ~[spring-aop-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at com.sun.proxy.$Proxy46.getJobInstances(Unknown Source) ~[na:na]
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.getNextJobParameters(JobLauncherCommandLineRunner.java:131) ~[spring-boot-autoconfigure-1.5.3.RELEASE.jar:1.5.3.RELEASE]
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.execute(JobLauncherCommandLineRunner.java:212) ~[spring-boot-autoconfigure-1.5.3.RELEASE.jar:1.5.3.RELEASE]
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.executeLocalJobs(JobLauncherCommandLineRunner.java:231) ~[spring-boot-autoconfigure-1.5.3.RELEASE.jar:1.5.3.RELEASE]
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.launchJobFromProperties(JobLauncherCommandLineRunner.java:123) ~[spring-boot-autoconfigure-1.5.3.RELEASE.jar:1.5.3.RELEASE]
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.run(JobLauncherCommandLineRunner.java:117) ~[spring-boot-autoconfigure-1.5.3.RELEASE.jar:1.5.3.RELEASE]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:776) [spring-boot-1.5.3.RELEASE.jar:1.5.3.RELEASE]
... 6 common frames omitted
我发现了一个 jira https://jira.spring.io/browse/BATCH-2537,上面写着“带有 @EnableBatchProcessing 的 @Primary 数据源不适用于使用多个数据源”如果这是正确的,请告诉我如何实现相同的目标。 我还发现了这个How to use 2 or more databases with spring?,但对我的情况没有帮助。
【问题讨论】:
首先,我建议为批处理基础架构创建 2 个配置 1,另一个只包含您的作业配置(步骤等)。您的批处理配置应该配置批处理基础设施本身,而不是依赖于配置的默认批处理。为此,您自己实现BatchConfigurer
并禁用批量自动配置(您可以尝试删除 @EnableBatchProcessing
并查看 Spring Boot 如何处理自动配置(而不是普通的 Spring Batch)。
感谢您的回复@M.Deinum,对不起,我是 spring boot 和 batch 的新手。如果您将更具描述性,那将对我有所帮助,或者如果可以提供一个示例,请提前致谢:)
最短的,删除@EnableBatchProcessing
,看看会发生什么。如果这不起作用,请按照说明进行操作,将配置拆分为 2 并让基础架构配置实现BatchConfigurer
。
【参考方案1】:
正如 M. Deinum 所建议的,我还将数据源的配置放在一个单独的文件中。
除此之外,你的配置文件还存在以下问题:
SpringBatch 查找名为“dataSource”的数据源(注意大写的 S)。如果没有找到,它会查找它找到的任何数据源。但是,如果它发现不止一个,它会抛出一个异常 -> 你观察到的那个。
在您的配置文件中,您创建两个数据源并注入一个 (@Autowired Datasource dataSourceSecond)。这将导致下一个问题,因为您没有具有此名称的数据源。 (您只定义了数据源“secondaryDataSource”和“primaryDataSource”)。这也会导致异常。
这是我组织配置的方式
@Configuration
public DatasourceConfiguration
@Bean
@ConfigurationProperties(prefix="spring.seconddatasource")
public javax.sql.DataSource secondaryDataSource()
return DataSourceBuilder.create().build();
// note the new name: dataSource -> this is the name springBatch is looking for
@Bean
@ConfigurationProperties(prefix="spring.datasource")
public javax.sql.DataSource dataSource()
return DataSourceBuilder.create().build();
@Configuration
@EnableBatchProcessing
@Import(DatasourceConfiguration.class)
public class BatchConfiguration
@Autowired
public JobBuilderFactory jobBuilderFactory;
@Autowired
public StepBuilderFactory stepBuilderFactory;
// note the name
@Autowired
public DataSource secondaryDataSource;
@Bean
public JdbcCursorItemReader<User> reader()
JdbcCursorItemReader<User> reader=new JdbcCursorItemReader<>();
// note the name
reader.setDataSource(secondaryDataSource);
reader.setSql("Select ACCT_ID from ACCT_table FETCH FIRST 100 ROWS ONLY");
reader.setRowMapper(new UserRowerMapper());
return reader;
...
我还为类似问题写了一个更彻底的答案: I would like to create a spring batch project where batch does not use my datasource
【讨论】:
以上是关于要使用默认的 BatchConfigurer,上下文必须包含不超过一个 DataSource,找到 2的主要内容,如果未能解决你的问题,请参考以下文章