Spring Boot + Spring Batch无需使用DataSource

14

我正在尝试在Spring Boot项目中配置Spring Batch,并希望在没有数据源的情况下使用它。我发现ResourcelessTransactionManager是可行的方法,但我无法使其工作。问题在于我已经定义了3个其他的数据源,但我不想在Spring Batch中使用任何一个。

我检查了默认实现DefaultBatchConfigurer,如果它找不到数据源,它将执行我想要的操作。问题是我有3个数据源,都不想使用。

请不要建议使用HSQL或其他内存数据库,因为我不想用那个。


我认为你想要的是不可能的。至少使用一个内存数据库。 - Luca Basso Ricci
根据这个链接http://docs.spring.io/spring-batch/reference/html/configureJob.html#inMemoryRepository,如果我理解正确的话,应该是可以实现的。 - Majky
然后手动配置Spring Batch,不要使用自动配置。只需创建自己的BatchConfigurer,以实现所需功能。将其注册为bean,即可在没有数据源的情况下配置批处理。 - M. Deinum
我已经这样做了,但它仍在寻找DataSource,找到3个然后失败了。 - Majky
我的回答这里有帮助吗? - Sabir Khan
5个回答

25
我通过扩展DefaultBatchConfigurer类来解决这个问题,使其忽略任何DataSource,因此它将配置一个基于Map的JobRepository。
示例:

我通过扩展DefaultBatchConfigurer类来解决这个问题,使其忽略任何DataSource,因此它将配置一个基于Map的JobRepository。

示例:

@Configuration
@EnableBatchProcessing
public class BatchConfig extends DefaultBatchConfigurer {   

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

5
谢谢Nandish,这对我很有用。我在Springboot应用程序中尝试了这个方法。我还必须在主类中的排除列表中添加一个类:@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) - Faraz

10

就我的情况而言,我将数据持久化到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) {
        }

        //..
    }

对我来说没问题。 - Anas ZAHOURI

4

2
这是我能让这种情况工作的唯一方法。需要澄清的是,你必须完全实现自己的BatchConfigurer类。仅仅扩展DefaultBatchConfigurer是不够的,因为它仍会寻找DataSource。我只是从DefaultBatchConfigurer中复制了相关片段。只要你的类标记为@Component,它就会优于其他类。 - Mac
1
另一个需要注意的地方是我需要使用模块化批处理配置,并控制我的配置类加载方式。我在GitHub上放了一个非常简单的演示项目,解释了其中涉及的部分:https://github.com/macdaddyaz/spring-batch-inmem - Mac

3

我们有一个类似的问题,我们使用Spring Boot JDBC,但不想将Spring Batch表存储在数据库中,但仍然想要使用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

1
spring.batch.initializer.enabled已被弃用。可能的替代方案是spring.batch.initialize-schema=never - Edgar Asatryan
感谢@Richard提供的有效解决方案。因为我正在使用Hibernate将其他对象保存到数据库中(不是与工作相关的表),所以我使用了JpaTransactionManager。 我将代码更改如下:
this.transactionManager = new JpaTransactionManager(entityManagerFactory)
其中entityManagerFactory是自动装配的。
- Kishor K

3

您可以尝试在@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,默认为同步执行程序。” - abaghel
没错,但我有三个数据源,但不想在批处理中使用任何一个。抱歉,我更新了我的问题。 - Majky
@Majky 试试这个答案和这个答案一起使用:https://dev59.com/zFkS5IYBdhLWcg3waV_D#42721313 - Faraz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接