在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管理? 要求就像在批处理步骤中我们需要以下内容。

  1. 从DS 1读取 – jpaItemReader
  2. 写信给DS2 – JPAItemwriter
  3. 从DS2读取 – JPAItemreader
  4. 写信给Ds1 – JPAItemwriter
  5. 提交所有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", ""}); } 

}

该解决方案中的三个关键点:

  1. 该类使用@EnableBatchProcessing@Configuration注释,以及从DefaultBatchConfigurer扩展。 通过这样做,我们指示spring-batch在AbstractBatchConfiguration尝试查找BatchConfigurer时使用我们的自定义批处理配置器;
  2. 将batchDataSource bean注释为@Primary ,它指示spring-batch使用此数据源作为存储9个作业相关表的数据源。
  3. 覆盖protected JobRepository createJobRepository() throws Exception方法,该方法使jobRepository bean使用主数据源,并使用与其他数据源不同的transactionManager实例。