복붙노트

[SPRING] 데이터베이스에 메타 데이터를 지속시키지 않고 Spring-Batch?

SPRING

데이터베이스에 메타 데이터를 지속시키지 않고 Spring-Batch?

스프링 배치 작업을 만들고 싶지만 데이터베이스 지속성없이 실행하고 싶습니다. 불행히도 spring-batch는 어떻게 든 데이터베이스에 작업주기 메타 데이터를 작성해야하므로 transactionmanager와 entitymanager로 적어도 어떤 종류의 db를 제공 할 수 있도록 해줍니다.

메타 데이터를 방지하고 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) [?:?]

해결법

  1. ==============================

    1.MapJobRepositoryFactoryBean 및 ResourcelessTransactionManager를 사용할 수 있습니다.

    MapJobRepositoryFactoryBean 및 ResourcelessTransactionManager를 사용할 수 있습니다.

    샘플 구성 :

    <bean id="transactionManager"
        class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
    
    <bean id="jobRepository"
        class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
        <property name="transactionManager" ref="transactionManager" />
    </bean>
    
    <bean id="jobLauncher"
        class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
        <property name="jobRepository" ref="jobRepository" />
    </bean>
    

    Spring 4.X의 경우 주석 기반 구성은 다음과 같습니다.

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

    2.일괄 구성의 데이터 소스없이 구성을 작성하기 만하면됩니다.

    일괄 구성의 데이터 소스없이 구성을 작성하기 만하면됩니다.

    @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

    스프링 부트로 자동 구성된 경우에도 프로덕션 데이터 원본을 사용할 수 있습니다.

  3. ==============================

    3.@ Braj의 대답을 조정하면, 내 작업 구성은 다음과 같습니다 :

    @ 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;
    }
    
  4. ==============================

    4.솔루션이 더 이상 작동하지 않아서 제 자신의 질문으로 돌아 왔습니다. spring-batch-1.5.3에서 다음과 같이 사용하십시오 :

    솔루션이 더 이상 작동하지 않아서 제 자신의 질문으로 돌아 왔습니다. spring-batch-1.5.3에서 다음과 같이 사용하십시오 :

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

    5.작업의 메타 데이터를 데이터베이스에 저장하지 않으려면 다음과 같은 구성이 필요합니다.

    작업의 메타 데이터를 데이터베이스에 저장하지 않으려면 다음과 같은 구성이 필요합니다.

    @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;
    

    스프링 배치는 해당 데이터 소스를 사용하여 내부 스키마 (BATCH_ * 테이블 및 시퀀스)를 생성합니다. 이 문제를 방지하려면 application.properties에서 spring.batch.initializer.enabled = false 플래그를 설정하십시오.

  6. ==============================

    6.@ Braj의 응답 외에도 일괄 자동 구성을 제외해야했습니다. @SpringBootApplication (exclude = {BatchAutoConfiguration.class})

    @ Braj의 응답 외에도 일괄 자동 구성을 제외해야했습니다. @SpringBootApplication (exclude = {BatchAutoConfiguration.class})

    그렇지 않으면 작동하지 않았습니다. 여기에는 Spring Boot 응용 프로그램이 포함됩니다.

  7. ==============================

    7.위의 모든 솔루션을 시도했지만 스프링 배치 작업에 멀티 스레딩과 같은 고급 기능이 있기 때문에 특정 시나리오에서는 작동하지 않습니다. 데이터베이스가 필요합니다. 그래서 여기에 내가 문제를 해결하기 위해 무엇을 했는가?

    위의 모든 솔루션을 시도했지만 스프링 배치 작업에 멀티 스레딩과 같은 고급 기능이 있기 때문에 특정 시나리오에서는 작동하지 않습니다. 데이터베이스가 필요합니다. 그래서 여기에 내가 문제를 해결하기 위해 무엇을 했는가?

    @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;
      }
    
    }
    
  8. ==============================

    8.제공된 모든 대답을 읽은 후에 나는 그것을 작동 시켰습니다. 내가 회원 및 Aure77 솔루션의 혼합을 사용합니다. setDataSource 메서드를 재정의 할 필요가 없다는 것을 알았습니다. DefaultBatchConfigurer는 자동으로 PlatformTransactionManager를 처리하며 DataSource는 필요하지 않습니다. 스프링 부트 2.0.3.RELEASE를 사용 중입니다. 다음은 내가 사용한 방법입니다.

    제공된 모든 대답을 읽은 후에 나는 그것을 작동 시켰습니다. 내가 회원 및 Aure77 솔루션의 혼합을 사용합니다. setDataSource 메서드를 재정의 할 필요가 없다는 것을 알았습니다. DefaultBatchConfigurer는 자동으로 PlatformTransactionManager를 처리하며 DataSource는 필요하지 않습니다. 스프링 부트 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);
        }
    }
    
  9. ==============================

    9.가장 간단한 방법은 클래스 경로에 내장 된 데이터베이스를 추가하는 것입니다. 당연히 프로덕션에서는 권장되지 않지만 학습을 위해 사용한다면 시간을 절약하십시오.

    가장 간단한 방법은 클래스 경로에 내장 된 데이터베이스를 추가하는 것입니다. 당연히 프로덕션에서는 권장되지 않지만 학습을 위해 사용한다면 시간을 절약하십시오.

    pom.xml에 포함 된 H2 데이터베이스 종속성을 추가하십시오.

    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>runtime</scope>
    </dependency>
    

    그게 다야.

  10. from https://stackoverflow.com/questions/25077549/spring-batch-without-persisting-metadata-to-database by cc-by-sa and MIT license