有没有办法只为特定作业跳过 Spring Batch 的持久元数据?
Posted
技术标签:
【中文标题】有没有办法只为特定作业跳过 Spring Batch 的持久元数据?【英文标题】:Is there a way to skip persisting metadata for Spring Batch only for particular jobs? 【发布时间】:2020-02-20 12:28:05 【问题描述】:有几个示例说明我们如何使用 Spring Batch 而不将元数据持久化到数据库中。以下是有关此事的一些示例和相关问题:
Spring-Batch without persisting metadata to database?
How to avoid Spring batch persistence of metadata in DB
Spring Batch - How to prevent batch from storing transactions in DB
Spring boot + spring batch without DataSource
但是我有一个稍微不同的用例:我有一些每隔一小时左右运行一次的作业,我想将其中的元数据保存到我的数据库中(例如,创建报告、运行一些测试,这两者都可能略有不同)处理量大)。我有一些其他类型的作业每分钟左右运行一次(例如,解锁由于重复输入错误密码等而被锁定的用户帐户),这些作业不涉及太多处理,而是一个简单的 sql 查询。
问题分为两部分:
有没有办法将第一类作业(例如报告处理)的元数据保留在数据库中,而对第二类作业(例如解锁用户帐户)完全不使用数据库持久性?
或者,甚至将 Spring Batch 用于第二种类型的作业是否过大/根本不需要?带有@Scheduled
注解的方法就够了吗?
【问题讨论】:
【参考方案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
自动配置的作业存储库使用。
或者,甚至将 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
。
【讨论】:
以上是关于有没有办法只为特定作业跳过 Spring Batch 的持久元数据?的主要内容,如果未能解决你的问题,请参考以下文章