我想创建一个批处理不使用我的数据源的spring批处理项目

我已经看到很多Spring Batch项目的例子,其中(a)定义了一个dataSource,或者(b)没有定义dataSource。

但是,在我的项目中,我希望我的业务逻辑可以访问dataSource,但我希望Spring Batch不使用dataSource。 这可能吗?

这家伙有类似的问题: Spring boot +没有DataSource的spring批处理

通常,使用没有数据库的spring-batch不是一个好主意,因为根据您定义的作业类型可能会出现并发问题。 因此,强烈建议至少使用内存数据库,特别是如果您计划在生产中使用该作业。

如果不配置自己的数据源,则将SpringBatch与SpringBoot一起使用将初始化内存数据源。

考虑到这一点,让我按照以下方式重新定义您的问题:我的businesslogic可以使用另一个数据源而不是springbatch用于更新其BATCH表吗? 是的,它可以。 事实上,您可以在SpringBatch Jobs中使用任意数量的数据源。 只需使用名称自动assembly。

我是这样做的:我总是使用Configuration类,它定义了我必须在Jobs中使用的所有数据源

Configuration public class DatasourceConfiguration { @Bean @ConditionalOnMissingBean(name = "dataSource") public DataSource dataSource() { // create datasource, that is used by springbatch // for instance, create an inmemory datasource using the // EmbeddedDatabaseFactory return ...; } @Bean @ConditionalOnMissingBean(name = "bl1datasource") public DataSource bl1datasource() { return ...; // your first datasource that is used in your businesslogic } @Bean @ConditionalOnMissingBean(name = "bl2datasource") public DataSource bl2datasource() { return ...; // your second datasource that is used in your businesslogic } } 

要点三点:

SpringBatch正在寻找名为“dataSource”的数据源,如果你没有提供这个EXACT(大写’S’)名称作为名称,spring批次将尝试按类型自动assembly,如果找到多个DataSource实例,它会抛出exception。

将您的数据源配置放在自己的类中。 不要把它们放在与你的工作定义相同的类中。 Spring需要能够在加载上下文时尽早将名称为“dataSource”的数据源SpringBean实例化。 在它开始实例化你的Job-and-Step-Beans之前。 如果将数据源定义放在与作业/步骤定义相同的类中,Spring将无法正确执行此操作。

使用@ConditionalOnMissingBean不是强制性的,但我发现它是一个很好的实践。 它可以轻松更改单元/集成测试的数据源。 只需在单元/ IT测试的ContextConfiguration中提供一个额外的测试配置,例如,用inMemoryDataSource覆盖“bl1Datasource”:

 Configuration public class TestBL1DatasourceConfiguration { // overwritting bl1datasource with an inMemoryDatasource. @Bean public DataSource bl1datasource() { return new EmbeddedDatabaseFactory.getDatabase(); } } 

要使用businesslogic数据源,请按名称使用注入:

 @Component public class PrepareRe1Re2BezStepCreatorComponent { @Autowired private StepBuilderFactory stepBuilderFactory; @Autowired private DataSource bl1datasource; @Autowired private DataSource bl2datasource; public Step createStep() throws Exception { SimpleStepBuilder<..., ...> builder = stepBuilderFactory.get("astep") // .<..., ...> chunk(100) // .reader(createReader(bl1datasource)) // .writer(createWriter(bl2datasource)); // return builder.build(); } } 

此外,如果您想使用多个数据源,您可能需要考虑使用XA-Datasources。

编辑:

由于您似乎确实不想使用数据源,因此必须实现自己的BatchConfigurer( http://docs.spring.io/spring-batch/trunk/apidocs/org/springframework/batch/core/configuration /annotation/BatchConfigurer.html )(正如Michael Minella – SpringBatch项目负责人 – 上面指出的那样)。

您可以使用org.springframework.batch.core.configuration.annotation.DefaultBatchConfigurer的代码作为您自己实现的起点。 只需删除所有数据源/事务管理器代码,并在initialize方法中保留if (datasource === null)部分的内容。 这将初始化MapBasedJobRepository和MapBasedJobExplorer。 但同样,在生产环境中,这不是一个可用的解决方案,因为它不是线程安全的。

编辑:

如何实现它:

定义“businessDataSource”的配置类:

 @Configuration public class DataSourceConfigurationSimple { DataSource embeddedDataSource; @Bean public DataSource myBusinessDataSource() { if (embeddedDataSource == null) { EmbeddedDatabaseFactory factory = new EmbeddedDatabaseFactory(); embeddedDataSource = factory.getDatabase(); } return embeddedDataSource; } } 

特定BatchConfigurer的实现:(当然,必须实现这些方法……)

 public class MyBatchConfigurer implements BatchConfigurer { @Override public JobRepository getJobRepository() throws Exception { return null; } @Override public PlatformTransactionManager getTransactionManager() throws Exception { return null; } @Override public JobLauncher getJobLauncher() throws Exception { return null; } @Override public JobExplorer getJobExplorer() throws Exception { return null; } } 

最后是主要配置和启动类:

 @SpringBootApplication @Configuration @EnableBatchProcessing // Importing MyBatchConfigurer will install your BatchConfigurer instead of // SpringBatch default configurer. @Import({DataSourceConfigurationSimple.class, MyBatchConfigurer.class}) public class SimpleTestJob { @Autowired private JobBuilderFactory jobs; @Autowired private StepBuilderFactory steps; @Bean public Job job() throws Exception { SimpleJobBuilder standardJob = this.jobs.get(JOB_NAME) .start(step1()); return standardJob.build(); } protected Step step1() throws Exception { TaskletStepBuilder standardStep1 = this.steps.get("SimpleTest_step1_Step") .tasklet(tasklet()); return standardStep1.build(); } protected Tasklet tasklet() { return (contribution, context) -> { System.out.println("tasklet called"); return RepeatStatus.FINISHED; }; } public static void main(String[] args) throws Exception { SpringApplication.run(SimpleTestJob.class, args); } }