Notice
Recent Posts
Recent Comments
Link
«   2025/07   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Tags more
Archives
Today
Total
관리 메뉴

두리공장

[Spring batch] Step 7 - Multi DataSource 사용하기 본문

java

[Spring batch] Step 7 - Multi DataSource 사용하기

두리공장 2022. 5. 24. 22:52

스프링 배치를 구성하다보면, 배치용 메타DB는 H2 인메모리DB를 사용하고,
데이터 소스는 다양하게 연결할 경우도 있다.
이제, 여러 데이터소스를 연결하는 방법을 살펴보자

application.yml 에 다양한 데이터 소스를 설정한다.

spring:
  default:
    jdbc:
      driver-class-name: org.h2.Driver
      url: jdbc:h2:mem:userdb
      username: sa
      password:

  mariadb:
    jdbc:
      url: jdbc:mariadb://localhost:3306/test_db
      username: {userid}
      password: {password}
      driver-class-name: org.mariadb.jdbc.Driver

  postgres:
    jdbc:
      url: jdbc:postgresql://localhost:5432/user_db
      username: {userid}
      password: {password}
      driver-class-name: org.postgresql.Driver

  batch:
    jdbc:
      initialize-schema: always
    job:
      names: jobForExec

H2는 휘발성 DB(인메모리)로 사용하기로 해서 h2:mem 으로 설정해 보았다. 휘발성DB이기 때문에 프로세스 생성시 스키마가 자동으로 생성되도록 initalize-schema를 always로 설정한다.

데이터 소스Bean을 만든다.

@Configuration
public class DataSourceConfig {
    @Value("${spring.default.jdbc.driver-class-name}")
    private String defaultDriverClassName;
    @Value("${spring.default.jdbc.url}")
    private String defaultJdbcUrl;
    @Value("${spring.default.jdbc.username}")
    private String defaultJdbcUsername;
    @Value("${spring.default.jdbc.password}")
    private String defaultJdbcPassword;

    @Value("${spring.mariadb.jdbc.driver-class-name}")
    private String mariadbDriverClassName;
    @Value("${spring.mariadb.jdbc.url}")
    private String mariadbJdbcUrl;
    @Value("${spring.mariadb.jdbc.username}")
    private String mariadbJdbcUsername;
    @Value("${spring.mariadb.jdbc.password}")
    private String mariadbJdbcPassword;

    @Value("${spring.postgres.jdbc.driver-class-name}")
    private String postgresDriverClassName;
    @Value("${spring.postgres.jdbc.url}")
    private String postgresJdbcUrl;
    @Value("${spring.postgres.jdbc.username}")
    private String postgresJdbcUsername;
    @Value("${spring.postgres.jdbc.password}")
    private String postgresJdbcPassword;

    @Primary
    @Bean(name="defaultDataSource")
    public DataSource defaultDataSource(){
        return getDataSource(defaultDriverClassName,defaultJdbcUrl,defaultJdbcUsername,defaultJdbcPassword);
    }

    @Bean(name="mariadbDataSource")
    public DataSource mariadbDataSource(){
        return getDataSource(mariadbDriverClassName,mariadbJdbcUrl,mariadbJdbcUsername,mariadbJdbcPassword);
    }

    @Bean(name="postgresDataSource")
    public DataSource postgresDataSource(){
        return getDataSource(postgresDriverClassName,postgresJdbcUrl,postgresJdbcUsername,postgresJdbcPassword);
    }

    private DataSource getDataSource(String driverClassName, String url, String username, String password){
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName(driverClassName);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }
}

H2는 @Primary 어노테이션을 주어서 메타DB로 사용한다.
나머지 데이터 소스는 Bean에 name="" 을 주어서 alias을 설정해 두자.

Batch Job 에 DataSource를 연결하자

@EnableBatchProcessing
@SpringBootApplication
public class BatchApplication {
    @Autowired
    private JobBuilderFactory jobBuilderFactory;

    @Autowired
    private StepBuilderFactory stepBuilderFactory;
    
    @Autowired @Qualifier("mariadbDataSource")
    private DataSource mariadbDataSource;
    
    // DB를 읽기위한 ItemReader 이다.
    @Bean
    @StepScope
    public JdbcPagingItemReader<Ranking> rankingItemReader2(
            DataSource dataSource
    ) throws Exception {
        
        return new JdbcPagingItemReaderBuilder<Ranking>()
                .name("rankingItemReader")
                .dataSource(mariadbDataSource)
                .queryProvider(pagingQueryProvider(mariadbDataSource))
                .pageSize(10)
                .rowMapper(new BeanPropertyRowMapper<>(Ranking.class))
                .build();
    }
    
    @Bean
    public PagingQueryProvider pagingQueryProvider(DataSource dataSource) throws Exception {
        SqlPagingQueryProviderFactoryBean factoryBean = new SqlPagingQueryProviderFactoryBean();
        factoryBean.setSelectClause("select *");
        factoryBean.setFromClause("from spi_global_rankings");
        //factoryBean.setWhereClause("where rank = :rank");
        factoryBean.setSortKey("rank");
        factoryBean.setDataSource(mariadbDataSource);
        return factoryBean.getObject();
    }
    
    //스텝을 만든다.
    @Bean
    public Step stepForExec() throws Exception {
        return this.stepBuilderFactory.get("stepForExec")
                .<Ranking, Ranking>chunk(1)
                .reader(rankingItemReader2(mariadbDataSource))
                .writer(execItemWriter(null))
                .build();
    }
    
    //잡을 만든다.
    @Bean
    public Job jobForExec() throws Exception {
        return this.jobBuilderFactory.get("jobForExec")
                .start(stepForExec())
                .build();
    }

    public static void main(String[] args) {
        SpringApplication.run(BatchApplication.class, args);
    }
}

출력 결과

2022-05-24 22:49:53.235  INFO 7332 --- [           main] com.sunnier.batch.BatchApplication       : Starting BatchApplication using Java 1.8.0_202 on DESKTOP-AHN11RT with PID 7332 (C:\git_repo\batch\target\classes started by sunni in C:\git_repo\batch)
2022-05-24 22:49:53.238  INFO 7332 --- [           main] com.sunnier.batch.BatchApplication       : No active profile set, falling back to 1 default profile: "default"
2022-05-24 22:50:24.403  INFO 7332 --- [           main] o.s.b.c.r.s.JobRepositoryFactoryBean     : No database type set, using meta data indicating: H2
2022-05-24 22:50:24.517  INFO 7332 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : No TaskExecutor has been set, defaulting to synchronous executor.
2022-05-24 22:50:24.622  INFO 7332 --- [           main] com.sunnier.batch.BatchApplication       : Started BatchApplication in 31.918 seconds (JVM running for 33.383)
2022-05-24 22:50:24.624  INFO 7332 --- [           main] o.s.b.a.b.JobLauncherApplicationRunner   : Running default command line with: [argu=foo12]
2022-05-24 22:50:24.696  INFO 7332 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=jobForExec]] launched with the following parameters: [{argu=foo12}]
2022-05-24 22:50:24.739  INFO 7332 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Executing step: [stepForExec]

H2가 메타DB로 만들어지고 배치가 실행된다.