Spring-Batch没有将元数据保存到数据库?

我想创建一个spring-batch作业,但我想在没有任何数据库持久性的情况下运行它。 不幸的是,spring-batch需要以某种方式将作业循环中的metadata写入数据库,从而促使我至少提供某种db与transactionmanager和entitymanager。

是否可以阻止元数据并独立于txmanagers和数据库运行?

更新:

 ERROR org.springframework.batch.core.job.AbstractJob: Encountered fatal error executing job java.lang.NullPointerException at org.springframework.batch.core.repository.dao.MapJobExecutionDao.synchronizeStatus(MapJobExecutionDao.java:158) ~[spring-batch-core-3.0.1.RELEASE.jar:3.0.1.RELEASE] at org.springframework.batch.core.repository.support.SimpleJobRepository.update(SimpleJobRepository.java:161) ~[spring-batch-core-3.0.1.RELEASE.jar:3.0.1.RELEASE] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.7.0_51] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[?:1.7.0_51] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.7.0_51] at java.lang.reflect.Method.invoke(Method.java:606) ~[?:1.7.0_51] at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) ~[spring-aop-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) ~[spring-aop-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98) ~[spring-tx-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262) ~[spring-tx-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95) ~[spring-tx-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) ~[spring-aop-4.0.6.RELEASE.jar:4.0.6.RELEASE] at com.sun.proxy.$Proxy134.update(Unknown Source) ~[?:?] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.7.0_51] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[?:1.7.0_51] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.7.0_51] at java.lang.reflect.Method.invoke(Method.java:606) ~[?:1.7.0_51] at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) ~[spring-aop-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) ~[spring-aop-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:127) ~[spring-batch-core-3.0.1.RELEASE.jar:3.0.1.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) ~[spring-aop-4.0.6.RELEASE.jar:4.0.6.RELEASE] at com.sun.proxy.$Proxy134.update(Unknown Source) ~[?:?] at org.springframework.batch.core.job.AbstractJob.updateStatus(AbstractJob.java:416) ~[spring-batch-core-3.0.1.RELEASE.jar:3.0.1.RELEASE] at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:299) [spring-batch-core-3.0.1.RELEASE.jar:3.0.1.RELEASE] at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:135) [spring-batch-core-3.0.1.RELEASE.jar:3.0.1.RELEASE] at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) [spring-core-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:128) [spring-batch-core-3.0.1.RELEASE.jar:3.0.1.RELEASE] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.7.0_51] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[?:1.7.0_51] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.7.0_51] at java.lang.reflect.Method.invoke(Method.java:606) ~[?:1.7.0_51] at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) [spring-aop-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) [spring-aop-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) [spring-aop-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:127) [spring-batch-core-3.0.1.RELEASE.jar:3.0.1.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [spring-aop-4.0.6.RELEASE.jar:4.0.6.RELEASE] at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) [spring-aop-4.0.6.RELEASE.jar:4.0.6.RELEASE] at com.sun.proxy.$Proxy50.run(Unknown Source) [?:?] 

我想在没有任何数据库持久性的情况下运行它

您可以使用MapJobRepositoryFactoryBeanResourcelessTransactionManager

样本配置:

        

对于Spring 4.X,基于注释的配置如下:

 @Bean public PlatformTransactionManager getTransactionManager() { return new ResourcelessTransactionManager(); } @Bean public JobRepository getJobRepo() { return new MapJobRepositoryFactoryBean(getTransactionManager()).getObject(); } 

调整@ Braj的答案后,我的工作配置如下:

 @Bean public ResourcelessTransactionManager transactionManager() { return new ResourcelessTransactionManager(); } @Bean public JobRepository jobRepository(ResourcelessTransactionManager transactionManager) throws Exception { MapJobRepositoryFactoryBean mapJobRepositoryFactoryBean = new MapJobRepositoryFactoryBean(transactionManager); mapJobRepositoryFactoryBean.setTransactionManager(transactionManager); return mapJobRepositoryFactoryBean.getObject(); } @Bean public SimpleJobLauncher jobLauncher(JobRepository jobRepository) { SimpleJobLauncher simpleJobLauncher = new SimpleJobLauncher(); simpleJobLauncher.setJobRepository(jobRepository); return simpleJobLauncher; } 

只需为Batch配置创建没有数据源的配置:

 @Configuration @EnableAutoConfiguration @EnableBatchProcessing public class BatchConfiguration extends DefaultBatchConfigurer { @Override public void setDataSource(DataSource dataSource) { // override to do not set datasource even if a datasource exist. // initialize will use a Map based JobRepository (instead of database) } } 

它将使用基于内存映射的实现初始化JobRepository和JobExplorer。 https://github.com/spring-projects/spring-batch/blob/342d27bc1ed83312bdcd9c0cb30510f4c469e47d/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/DefaultBatchConfigurer.java#L84

即使自动配置弹簧启动,您也可以使用生产数据源。

我回到了自己的问题,因为解决方案不再适用了。 截至春季批次1.5.3使用如下:

 @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) ... @Bean public PlatformTransactionManager transactionManager() { return new ResourcelessTransactionManager(); } } 

如果您不想在数据库中存储作业的元数据,则配置如下所示

 @Configuration public class InMemoryJobRepositoryConfiguration { @Bean public ResourcelessTransactionManager transactionManager() { return new ResourcelessTransactionManager(); } @Bean public MapJobRepositoryFactoryBean mapJobRepositoryFactory(ResourcelessTransactionManager transactionManager) throws Exception { MapJobRepositoryFactoryBean factory = new MapJobRepositoryFactoryBean(transactionManager); factory.afterPropertiesSet(); return factory; } @Bean public JobRepository jobRepository(MapJobRepositoryFactoryBean repositoryFactory) throws Exception { return repositoryFactory.getObject(); } @Bean public JobExplorer jobExplorer(MapJobRepositoryFactoryBean repositoryFactory) { return new SimpleJobExplorer(repositoryFactory.getJobInstanceDao(), repositoryFactory.getJobExecutionDao(), repositoryFactory.getStepExecutionDao(), repositoryFactory.getExecutionContextDao()); } @Bean public SimpleJobLauncher jobLauncher(JobRepository jobRepository) { SimpleJobLauncher launcher = new SimpleJobLauncher(); launcher.setJobRepository(jobRepository); return launcher; } } 

如果作业需要读取/写入数据库的业务数据,并且数据源配置如下。

 @Autowired private DataSource dataSource; 

spring批处理使用该数据源创建内部模式(BATCH_ *表和序列)。 为防止这种情况发生,请在application.properties中设置标志spring.batch.initializer.enabled=false

除了@Braj-s响应之外,我不得不排除批量自动配置: @SpringBootApplication(exclude = {BatchAutoConfiguration.class})

它没有其他工作。 这包括Spring Boot应用程序

我尝试了上面的所有解决方案,但它不适用于我的特定场景,因为我的spring批处理作业具有multithreading等高级function。 它需要一个数据库。 以下是我为解决问题所做的工作:

 @Configuration public class FakeBatchConfig implements BatchConfigurer { PlatformTransactionManager transactionManager; JobRepository jobRepository; JobLauncher jobLauncher; JobExplorer jobExplorer; @Override public JobRepository getJobRepository() { return jobRepository; } @Override public PlatformTransactionManager getTransactionManager() { return transactionManager; } @Override public JobLauncher getJobLauncher() { return jobLauncher; } @Override public JobExplorer getJobExplorer() { return jobExplorer; } @PostConstruct void initialize() throws Exception { if (this.transactionManager == null) { this.transactionManager = new ResourcelessTransactionManager(); } MapJobRepositoryFactoryBean jobRepositoryFactory = new MapJobRepositoryFactoryBean(this.transactionManager); jobRepositoryFactory.afterPropertiesSet(); this.jobRepository = jobRepositoryFactory.getObject(); MapJobExplorerFactoryBean jobExplorerFactory = new MapJobExplorerFactoryBean(jobRepositoryFactory); jobExplorerFactory.afterPropertiesSet(); this.jobExplorer = jobExplorerFactory.getObject(); this.jobLauncher = createJobLauncher(); } private JobLauncher createJobLauncher() throws Exception { SimpleJobLauncher jobLauncher = new SimpleJobLauncher(); jobLauncher.setJobRepository(jobRepository); jobLauncher.afterPropertiesSet(); return jobLauncher; } } 

在阅读了所有提供的答案后,我得到了它的工作。 我使用了memberound和Aure77解决方案的混合。 我发现没有必要覆盖setDataSource方法。 DefaultBatchConfigurer自动处理PlatformTransactionManager,不需要DataSource。 请注意我使用的是Spring boot 2.0.3.RELEASE。 以下是我使用的方法

 @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }) @EnableBatchProcessing public class DemoApplication extends DefaultBatchConfigurer { @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(DemoApplication.class, args))); SpringApplication.run(DemoApplication.class, args); } } 

最简单的是向classpath添加嵌入式数据库。 当然不建议在生产中使用,但如果您正在使用它来学习,请节省时间。

将pom.xml添加到嵌入式H2数据库依赖项中:

  com.h2database h2 runtime  

就这样。