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

Posted

技术标签:

【中文标题】我想创建一个批处理不使用我的数据源的春季批处理项目【英文标题】:I would like to create a spring batch project where batch does not use my datasource 【发布时间】:2017-03-26 00:55:31 【问题描述】:

我见过很多 Spring Batch 项目的示例,其中 (a) 定义了数据源,或 (b) 未定义数据源。

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

这家伙也有类似的问题:Spring boot + spring batch without DataSource

【问题讨论】:

我回答了另一个问题(因为不赞成在 *** 上重复问题):***.com/a/40680502/618059 Spring boot + spring batch without DataSource的可能重复 让我澄清一下 - 我想为我的业务逻辑使用数据源,但我不希望 Spring Batch 使用数据源。我提供的链接指向另一个问题,即该人不想使用 any 数据源。我的问题不是重复的。 【参考方案1】:

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

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

考虑到这一点,让我重新定义您的问题如下:我的业务逻辑能否使用 springbatch 用于更新其 BATCH 表的另一个数据源? 是的,它可以。事实上,您可以在 SpringBatch 作业中使用任意数量的数据源。只需使用按名称自动装配。

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

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 Batch 将尝试按类型自动装配,如果它找到多个实例的DataSource,它会抛出一个异常。

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

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

Configuration
public class TestBL1DatasourceConfiguration 

    // overwritting bl1datasource with an inMemoryDatasource.
    @Bean
    public DataSource bl1datasource() 
        return new EmbeddedDatabaseFactory.getDatabase(); 
    

为了使用业务逻辑数据源,按名称使用注入:

@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)(正如上面提到的 SpringBatch 项目负责人 Michael Minella)。

您可以使用 org.springframework.batch.core.configuration.annotation.DefaultBatchConfigurer 的代码作为您自己实现的起点。只需删除所有数据源/事务管理器代码并将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);
    

【讨论】:

您已经展示了如何配置 Spring Batch 以使用与我的业务逻辑不同的数据源。这不是我问的。我问是否可以阻止 Spring Batch 使用数据源,同时仍将数据源用于我的业务逻辑。 我知道,因为这是您应该要求的。 :-) 正如我在回答开头指出的那样,有充分的理由说明您至少应该将内存数据库与弹簧批处理一起使用。但无论如何,我添加了一些关于如何编写自己的 BatchConfigurer 的注释。 感谢您终于尝试回答我的问题。让我问你这个问题:你真的得到了使用你的解决方案的实现吗?因为我已经尝试过创建自定义 BatchConfigurer,但没有成功。

以上是关于我想创建一个批处理不使用我的数据源的春季批处理项目的主要内容,如果未能解决你的问题,请参考以下文章

春季批处理继续运行

春季批项目阅读

春季批处理写入器限制

有没有办法 MySQLMaxValueIncrementer 在春季批处理中连接到多个数据源

春季 JPQL 处理日期

事务未在春季批处理项目编写器中回滚