在Spring Batch中使用多个DataSource
我试图在Spring Batch中配置几个数据源。 在启动时,Spring Batch抛出以下exception:
To use the default BatchConfigurer the context must contain no more thanone DataSource, found 2
批量配置的代码段
@Configuration @EnableBatchProcessing public class BatchJobConfiguration { @Primary @Bean(name = "baseDatasource") public DataSource dataSource() { // first datasource definition here } @Bean(name = "secondaryDataSource") public DataSource dataSource2() { // second datasource definition here } ... }
不知道为什么我看到这个exception,因为我已经看到一些基于xml的Spring批处理配置声明了多个数据源。 我使用Spring Batch核心版本3.0.1.RELEASE与Spring Boot版本1.1.5.RELEASE。 任何帮助将不胜感激。
AbstractBatchConfiguration
尝试在容器中查找BatchConfigurer
,如果找不到,则尝试自己创建它 – 这是在容器中有多个DataSource
bean的地方IllegalStateException
的地方。
解决问题的方法是防止在AbstractBatchConfiguration
创建DefaultBatchConfigurer
bean。 为此,我们提示使用@Component
注释通过Spring容器创建DefaultBatchConfigurer
:
放置@EnableBatchProcessing
的配置类我们可以用@ComponentScan
注释,它扫描包含从DefaultBatchConfigurer
派生的空类的包:
package batch_config; ... @EnableBatchProcessing @ComponentScan(basePackageClasses = MyBatchConfigurer.class) public class MyBatchConfig { ... }
这个空派生类的完整代码在这里:
package batch_config.components; import org.springframework.batch.core.configuration.annotation.DefaultBatchConfigurer; import org.springframework.stereotype.Component; @Component public class MyBatchConfigurer extends DefaultBatchConfigurer { }
在此配置中, @Primary
注释适用于DataSource
bean,如下例所示:
@Configuration public class BatchTestDatabaseConfig { @Bean @Primary public DataSource dataSource() { return .........; } }
这适用于Spring Batch版本3.0.3.RELEASE
在DataSource
上进行@Primary
注释的最简单的解决方案可能只是添加@ComponentScan(basePackageClasses = DefaultBatchConfigurer.class)
以及@EnableBatchProcessing
注释:
@Configuration @EnableBatchProcessing @ComponentScan(basePackageClasses = DefaultBatchConfigurer.class) public class MyBatchConfig {
您必须提供自己的BatchConfigurer。 Spring不想为你做出决定
@Configuration @EnableBatchProcessing public class BatchConfig { @Bean BatchConfigurer configurer(@Qualifier("batchDataSource") DataSource dataSource){ return new DefaultBatchConfigurer(dataSource); } ...
如果我可以添加上述问题,那么每个DS有两个事务上下文的含义。 如何将XA事务与Batch步骤集成,因为我们需要确保步骤级别的TXN管理? 要求就像在批处理步骤中我们需要以下内容。
- 从DS 1读取 – jpaItemReader
- 写信给DS2 – JPAItemwriter
- 从DS2读取 – JPAItemreader
- 写信给Ds1 – JPAItemwriter
- 提交所有txns步骤完成。
最简单的解决方案是扩展DefaultBatchConfigurer并通过限定符自动assembly数据源:
@Component public class MyBatchConfigurer extends DefaultBatchConfigurer { /** * Initialize the BatchConfigurer to use the datasource of your choosing * @param firstDataSource */ @Autowired public MyBatchConfigurer(@Qualifier("firstDataSource") DataSource firstDataSource) { super(firstDataSource); } }
侧注(因为这也涉及多个数据源的使用):如果使用autoconfig运行数据初始化脚本,您可能会注意到它没有初始化您期望的数据源。 对于这个问题,请看一下: https : //github.com/spring-projects/spring-boot/issues/9528
首先,创建一个自定义BatchConfigurer
@Configuration @Component public class TwoDataSourcesBatchConfigurer implements BatchConfigurer { @Autowired @Qualifier("dataSource1") DataSource dataSource; @Override public JobExplorer getJobExplorer() throws Exception { ... } @Override public JobLauncher getJobLauncher() throws Exception { ... } @Override public JobRepository getJobRepository() throws Exception { JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); // use the autowired data source factory.setDataSource(dataSource); factory.setTransactionManager(getTransactionManager()); factory.afterPropertiesSet(); return factory.getObject(); } @Override public PlatformTransactionManager getTransactionManager() throws Exception { ... } }
然后,
@Configuration @EnableBatchProcessing @ComponentScan("package") public class JobConfig { // define job, step, ... }
我想在这里提供一个解决方案,它与@vanarchi回答的解决方案非常相似,但我设法将所有必要的配置放在一个类中。
为了完整起见,此处的解决方案假定主数据源是hsql。
@Configuration @EnableBatchProcessing public class BatchConfiguration extends DefaultBatchConfigurer { @Bean @Primary public DataSource batchDataSource() { // no need shutdown, EmbeddedDatabaseFactoryBean will take care of this EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); EmbeddedDatabase embeddedDatabase = builder .addScript("classpath:org/springframework/batch/core/schema-drop-hsqldb.sql") .addScript("classpath:org/springframework/batch/core/schema-hsqldb.sql") .setType(EmbeddedDatabaseType.HSQL) //.H2 or .DERBY .build(); return embeddedDatabase; } @Override protected JobRepository createJobRepository() throws Exception { JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); factory.setDataSource(batchDataSource()); factory.setTransactionManager(transactionManager()); factory.afterPropertiesSet(); return (JobRepository) factory.getObject(); } private ResourcelessTransactionManager transactionManager() { return new ResourcelessTransactionManager(); } //NOTE: the code below is just to provide developer an easy way to access the in-momery hsql datasource, as we configured it to the primary datasource to store batch job related data. Default username : sa, password : '' @PostConstruct public void getDbManager(){ DatabaseManagerSwing.main( new String[] { "--url", "jdbc:hsqldb:mem:testdb", "--user", "sa", "--password", ""}); }
}
该解决方案中的三个关键点:
- 该类使用
@EnableBatchProcessing
和@Configuration
注释,以及从DefaultBatchConfigurer
扩展。 通过这样做,我们指示spring-batch在AbstractBatchConfiguration
尝试查找BatchConfigurer
时使用我们的自定义批处理配置器; - 将batchDataSource bean注释为
@Primary
,它指示spring-batch使用此数据源作为存储9个作业相关表的数据源。 - 覆盖
protected JobRepository createJobRepository() throws Exception
方法,该方法使jobRepository bean使用主数据源,并使用与其他数据源不同的transactionManager实例。
- 如何将JRBeanCollectionDataSource传递给iReport?
- 属性’dataSource’是必需的java(Spring)错误
- 无法通过JBoss远程访问数据源
- MyBatis-guice 3.3 +多个数据源+属性+ scriptrunner
- 轻松启动独立JNDI服务器(并注册一些资源)
- 带有mysql DataSource的javax.naming.NoInitialContextException
- Out容器JNDI数据源
- java.lang.AbstractMethodError:com.mysql.jdbc.Connection.isValid(I)Z
- 在Spring Boot中的每个数据库连接的开头运行SQL语句