【问题标题】:Spring boot + spring batch without DataSource没有数据源的 Spring Boot + Spring Batch
【发布时间】:2017-02-16 06:09:50
【问题描述】:

我正在尝试在 Spring Boot 项目中配置 Spring Batch,我想在没有数据源的情况下使用它。我发现ResourcelessTransactionManager 是要走的路,但我无法让它发挥作用。问题是我已经定义了另外 3 个数据源,但我不想在 springBatch 中使用它们中的任何一个。

我已经检查了默认实现 DefaultBatchConfigurer,如果它无法找到 dataSource,它将完全按照我的意愿执行。问题是我有 3 个,不想使用任何一个。

请不要建议在内存数据库中使用 hsql 或其他我不想要的。

【问题讨论】:

  • 我认为你想要的是不可能的。至少使用内存数据库
  • 据此docs.spring.io/spring-batch/reference/html/…如果我理解正确应该是可以的。
  • 然后手动配置Spring Batch,不要使用自动配置。只需创建您自己的 BatchConfigurer 即可满足您的需求。将其注册为 bean,批处理将被配置为没有数据源。
  • 我已经这样做了,它仍在寻找 DataSource,找到其中 3 个然后它失败了。
  • 我的回答here 有帮助吗?

标签: java spring spring-boot spring-batch


【解决方案1】:

就我而言,我将数据保存到 Cassandra。如果您使用的是 spring-boot-starter-batch,它预计会提供一个尚未实现的 DataSource,但您可以像以下步骤一样欺骗配置:

第一步:

@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class SampleSpringBatchApplication{

    public static void main(String[] args) {
        System.setProperty("spring.devtools.restart.enabled", "true");
        SpringApplication.run(SampleSpringBatchApplication.class, args);
    }

}

第二步:

    @Configuration
    @EnableBatchProcessing
    public class SampleBatchJob extends DefaultBatchConfigurer {

        //..

        @Override
        public void setDataSource(DataSource dataSource) {
        }

        //..
    }

【讨论】:

  • 这是我的工作。
【解决方案2】:

我们遇到了类似的问题,我们使用的是 spring boot JDBC,我们不想在 DB 中存储 spring 批处理表,但我们仍然想为我们的 DataSource 使用 spring 的事务管理。

我们最终实现了自己的 BatchConfigurer。

@Component
public class TablelessBatchConfigurer implements BatchConfigurer {
    private final PlatformTransactionManager transactionManager;
    private final JobRepository jobRepository;
    private final JobLauncher jobLauncher;
    private final JobExplorer jobExplorer;
    private final DataSource dataSource;

    @Autowired
    public TablelessBatchConfigurer(DataSource dataSource) {
        this.dataSource = dataSource;
        this.transactionManager = new DataSourceTransactionManager(this.dataSource);

        try {
            final MapJobRepositoryFactoryBean jobRepositoryFactory = new MapJobRepositoryFactoryBean(this.transactionManager);
            jobRepositoryFactory.afterPropertiesSet();
            this.jobRepository = jobRepositoryFactory.getObject();

            final MapJobExplorerFactoryBean jobExplorerFactory = new MapJobExplorerFactoryBean(jobRepositoryFactory);
            jobExplorerFactory.afterPropertiesSet();
            this.jobExplorer = jobExplorerFactory.getObject();

            final SimpleJobLauncher simpleJobLauncher = new SimpleJobLauncher();
            simpleJobLauncher.setJobRepository(this.jobRepository);
            simpleJobLauncher.afterPropertiesSet();
            this.jobLauncher = simpleJobLauncher;
        } catch (Exception e) {
            throw new BatchConfigurationException(e);
        }
    }
    // ... override getters
}

并将初始化程序设置为 false

spring.batch.initializer.enabled=false

【讨论】:

  • spring.batch.initializer.enabled 已弃用。 spring.batch.initialize-schema=never 可能是替代品。
  • 感谢@Richard 提供上述工作解决方案。当我使用 Hibernate 将其他对象保存在数据库中(不是与作业相关的表)时,我使用了 JpaTransactionManager。我在这个entityManagerFactory autowired 中更改了如下this.transactionManager = new JpaTransactionManager(entityManagerFactory) 的代码。
【解决方案3】:

我通过扩展 DefaultBatchConfigurer 类解决了这个问题,以便它忽略任何 DataSource,因此它将配置一个基于地图的 JobRepository。

例子:

@Configuration
@EnableBatchProcessing
public class BatchConfig extends DefaultBatchConfigurer {   

    @Override
    public void setDataSource(DataSource dataSource) {
        //This BatchConfigurer ignores any DataSource
    }
}

【讨论】:

  • 谢谢 Nandish,这对我有用。我在 Springboot 应用程序中试过这个。我还必须在主类的排除列表中添加一个类:@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
【解决方案4】:

如果您的配置中有多个DataSource(无论您是否想使用它们),您需要定义自己的BatchConfigurer。这是框架知道在这种情况下该做什么的唯一方法。

您可以在此处的文档中阅读有关 BatchConfigurer 的更多信息:http://docs.spring.io/spring-batch/trunk/apidocs/org/springframework/batch/core/configuration/annotation/BatchConfigurer.html

【讨论】:

  • 这是我能够让这个场景工作的唯一方法。不过,为了澄清,您必须完全实现您自己的BatchConfigurer 类。仅仅扩展DefaultBatchConfigurer 是不够的,因为它仍然会寻找DataSource。我刚刚从DefaultBatchConfigurer 中复制了相关的sn-ps。只要您的班级被标记为@Component,它就应该比其他班级更受青睐。
  • 另一个需要注意的是,我需要使用模块化批处理配置,并控制我的配置类的加载方式。我在 GitHub 上放了一个非常简单的演示项目,解释了涉及的部分:github.com/macdaddyaz/spring-batch-inmem
【解决方案5】:

您可以尝试在@SpringBootApplication 中排除DataSourceAutoConfiguration。请参阅下面的示例代码。

import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.Bean;

@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
@EnableBatchProcessing
public class SampleBatchApplication {

@Autowired
private JobBuilderFactory jobs;

@Autowired
private StepBuilderFactory steps;

@Bean
protected Tasklet tasklet() {

    return new Tasklet() {
        @Override
        public RepeatStatus execute(StepContribution contribution, ChunkContext context) {
            return RepeatStatus.FINISHED;
        }
    };
}

@Bean
public Job job() throws Exception {
    return this.jobs.get("job").start(step1()).build();
}

@Bean
protected Step step1() throws Exception {
    return this.steps.get("step1").tasklet(tasklet()).build();
}

public static void main(String[] args) throws Exception {
    System.exit(SpringApplication.exit(SpringApplication.run(SampleBatchApplication.class, args)));
   }
}

以及示例测试类

import org.junit.Rule;
import org.junit.Test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.test.rule.OutputCapture;
import static org.assertj.core.api.Assertions.assertThat;
public class SampleBatchApplicationTests {
@Rule
public OutputCapture outputCapture = new OutputCapture();

@Test
public void testDefaultSettings() throws Exception {
    assertThat(SpringApplication.exit(SpringApplication.run(SampleBatchApplication.class))).isEqualTo(0);
    String output = this.outputCapture.toString();
    assertThat(output).contains("completed with the following parameters");
  }
}

【讨论】:

  • 我已经添加了示例类和测试类。它对我有用。因为我不想使用数据源,所以我什至没有使用 ResourcelessTransactionManager 。当我运行它时,它会打印出“没有提供数据源...使用基于 Map 的 JobRepository”和“没有设置 TaskExecutor,默认为同步执行程序。”
  • 没错,但我有 3 个数据源,但不想将它们中的任何一个用于批处理。抱歉更新了我的问题。
  • @Majky 试试这个答案和这个答案:stackoverflow.com/a/42721313/4828463
猜你喜欢
  • 2018-01-27
  • 2016-04-17
  • 2019-01-19
  • 2018-10-24
  • 2014-04-10
  • 2018-07-10
  • 1970-01-01
  • 2016-08-08
  • 2017-09-27
相关资源
最近更新 更多