【问题标题】:Is there a way to skip persisting metadata for Spring Batch only for particular jobs?有没有办法只为特定作业跳过 Spring Batch 的持久元数据?
【发布时间】:2020-02-20 12:28:05
【问题描述】:

有几个示例说明我们如何使用 Spring Batch 而不将元数据持久化到数据库中。以下是有关此事的一些示例和相关问题:

但是我有一个稍微不同的用例:我有一些每隔一小时左右运行一次的作业,我想将其中的元数据保存到我的数据库中(例如,创建报告、运行一些测试,这两者都可能略有不同)处理量大)。我有一些其他类型的作业每分钟左右运行一次(例如,解锁由于重复输入错误密码等而被锁定的用户帐户),这些作业不涉及太多处理,而是一个简单的 sql 查询。

问题分为两部分:

  1. 有没有办法将第一类作业(例如报告处理)的元数据保留在数据库中,而对第二类作业(例如解锁用户帐户)完全不使用数据库持久性?

  2. 或者,甚至将 Spring Batch 用于第二种类型的作业是否过大/根本不需要?带有@Scheduled 注解的方法就够了吗?

【问题讨论】:

    标签: spring spring-boot spring-batch


    【解决方案1】:
    1. 有没有办法将第一类作业(例如报告处理)的元数据保留在数据库中,而对第二类作业(例如解锁用户帐户)完全不使用数据库持久性?

    这是配置问题。您可以使用 Spring profiles 作为数据源。这个想法是定义一个持久数据源和一个内存数据源。然后像往常一样使用数据源配置所有作业,并在运行时使用正确的配置文件运行它们。这是一个简单的例子:

    import javax.sql.DataSource;
    
    import com.zaxxer.hikari.HikariDataSource;
    
    import org.springframework.batch.core.Job;
    import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Profile;
    import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
    import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
    
    @Configuration
    @EnableBatchProcessing
    public class JobsConfiguration {
    
        @Bean
        public Job job1() {
            return null;
        }
    
        @Bean
        public Job job2() {
            return null;
        }
    
        @Bean
        @Profile("in-memory")
        public DataSource embeddedDataSource() {
            return new EmbeddedDatabaseBuilder()
                    .setType(EmbeddedDatabaseType.HSQL)
                    .addScript("/org/springframework/batch/core/schema-hsqldb.sql")
                    .build();
        }
    
        @Bean
        @Profile("persistent")
        public DataSource persistentDataSource() {
            HikariDataSource hikariDataSource = new HikariDataSource();
            // TODO configure datasource
            return hikariDataSource;
        }
    }
    

    如果您使用-Dspring.profiles.active=in-memory 运行您的应用程序,那么在您的应用程序上下文中将只有嵌入的数据源bean,它将被@EnableBatchProcessing 自动配置的作业存储库使用。

    1. 或者,甚至将 Spring Batch 用于第二种类型的作业是否过大/根本不需要?只需一个带有@Scheduled 注解的方法就足够了吗?

    which do not involve much of processing but a simple sql query:如果它是一个简单的 sql 查询并且您不需要保留元数据,那么最好使用带有 @Scheduled 注释的方法,该方法使用 jdbcTemplate 来运行查询。

    【讨论】:

    • 感谢您的回答。我需要一个关于如何告诉 Spring 为不同的工作使用不同的数据源的示例。可用配置仅允许我对所有作业使用单个数据源。我看不到为每个作业配置数据源的方法。
    • how to tell Spring to use different datasources for different jobs. : 使用配置文件的重点是使用单个数据源配置所有作业(不必为每个作业配置自己的数据源)并让spring根据在运行时选择的配置文件。我在答案中添加了一个示例。
    • "...然后像往常一样使用数据源配置所有作业..." 这与我想要实现的目标完全相反。你误解了这个问题。在同一个应用程序中,我有不止一项工作,我想使用不同的数据源运行。
    • 不,我收到了你的问题,我的示例故意包含 2 个工作。如果您使用 spring boot,您可以使用--spring.batch.job.names=job1 --spring.profiles.active=in-memory,您的 job1 将使用内存数据源运行。如果您不使用 spring boot,您仍然可以将配置文件添加到作业 bean 以及告诉 spring 哪个作业应该使用哪个数据源。
    • 但只有我的job1 可以运行吗?对于job2,我必须拥有另一个应用程序实例。
    【解决方案2】:

    关于 Mahmoud Ben Hassine 的建议,我是如何实现我正在寻找的东西的(删除 @EnableBatchProcessing,对于一些不相关的问题 - see here):

    我有两个配置类:

    @Configuration
    public class SpringBatchConfiguration extends DefaultBatchConfigurer {
    
        @Inject public SpringBatchConfiguration(DataSource dataSource) {
            super(dataSource);
        }
    
        @Bean(name = "persistentJobLauncher")
        public JobLauncher jobLauncher() throws Exception {
            return super.createJobLauncher();
        }
    
        @Bean
        @Primary
        public StepBuilderFactory stepBuilderFactory() {
            return new StepBuilderFactory(super.getJobRepository(), super.getTransactionManager());
        }
    
        @Bean
        @Primary
        public JobBuilderFactory jobBuilderFactory(){
            return new JobBuilderFactory(super.getJobRepository());
        }
    
        @Bean
        public JobExplorer jobExplorer() {
            return super.getJobExplorer();
        }
    
        @Bean
        public JobRepository jobRepository() {
            return super.getJobRepository();
        }
    
        @Bean
        public ListableJobLocator jobLocator() {
            return new MapJobRegistry();
        }
    }
    

    和内存中的一个:

    @Configuration
    public class SpringInMemoryBatchConfiguration extends DefaultBatchConfigurer {
    
        @Inject public SpringInMemoryBatchConfiguration() {
        }
    
        @Bean(name = "inMemoryJobLauncher")
        public JobLauncher inMemoryJobLauncher() throws Exception {
            return super.createJobLauncher();
        }
    
        @Bean(name = "inMemoryStepBuilderFactory")
        public StepBuilderFactory stepBuilderFactory() {
            return new StepBuilderFactory(super.getJobRepository(), super.getTransactionManager());
        }
    
        @Bean(name = "inMemoryJobBuilderFactory")
        public JobBuilderFactory inMemoryJobBuilderFactory(){
            return new JobBuilderFactory(super.getJobRepository());
        }
    }
    

    当我想开始一项“持久性”工作时,我使用@Qualifier(value = "persistentJobLauncher") JobLauncher launcher 并开始一项“内存中”工作:@Qualifier(value = "inMemoryJobLauncher") JobLauncher launcher

    【讨论】:

      猜你喜欢
      • 2020-02-23
      • 2016-11-09
      • 2023-04-06
      • 2011-05-06
      • 1970-01-01
      • 2020-03-20
      • 2020-09-24
      • 2021-12-04
      • 2019-10-23
      相关资源
      最近更新 更多