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 6 - DB를 읽어서 서비스 Method 호출하기 본문

java

[Spring batch] Step 6 - DB를 읽어서 서비스 Method 호출하기

두리공장 2022. 5. 22. 17:17

DB로 read 한후, method를 호출하는 배치를 만들어 본다.

1. 먼저 VO에 있는 데이터를 출력하는 service를 만든다.

@Service
public class RankingService {
    public void logRanking(Ranking rank) {
        System.out.println("I just save " + rank);
    }
}

2. 이제, ItemWriter 에서 해당 Service 의 logRanking 메서드를 호출해 보자

   //메서드를 실행하기 위한 배치아이템라이터
    @Bean
    public ItemWriterAdapter execItemWriter(RankingService rankingService) throws Exception {
        ItemWriterAdapter<Ranking> rankingItemWriterAdapter = new ItemWriterAdapter<>();
        rankingItemWriterAdapter.setTargetObject(rankingService);
        rankingItemWriterAdapter.setTargetMethod("logRanking");

        return rankingItemWriterAdapter;
    }

3. 당연히 아이템라이터를 실행하기 위한 스텝을 만들어야겠다.

    //스텝을 만든다.
    @Bean
    public Step stepForExec() throws Exception {
        return this.stepBuilderFactory.get("stepForExec")
                .<Ranking, Ranking>chunk(1)
                .reader(rankingItemReader2(null))
                .writer(execItemWriter(null))
                .build();
    }

rankingItemReader2 는 기존것을 사용하기로 했다..(jdbc로 Ranking 테이블을 읽어온다)

4. 그리고 이를 실행하기 위한 잡도 만들어야겠다.

    //잡을 만든다.
    @Bean
    public Job jobForExec() throws Exception {
        return this.jobBuilderFactory.get("jobForExec")
                .start(stepForExec())
                .build();
    }

5. 마지막으로 application.yml 에 실행할 잡의 이름을 넣어주자.

spring:
  datasource:
    url: jdbc:mariadb://localhost:3306/test_db
    username: {id}
    password: {password}
    driver-class-name: org.mariadb.jdbc.Driver
  batch:
    jdbc:
      initialize-schema: always
    job:
      names: jobForExec

6. 서비스를 실행하면, 아래와 같이 메서드가 실행된다.

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.6.4)

2022-05-22 17:06:48.755  INFO 8868 --- [           main] com.sunnier.batch.BatchApplication       : Starting BatchApplication using Java 1.8.0_202 on DESKTOP-AHN11RT with PID 8868 (C:\git_repo\batch\target\classes started by sunni in C:\git_repo\batch)
2022-05-22 17:06:48.755  INFO 8868 --- [           main] com.sunnier.batch.BatchApplication       : No active profile set, falling back to 1 default profile: "default"
2022-05-22 17:06:49.663  INFO 8868 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2022-05-22 17:06:49.728  INFO 8868 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2022-05-22 17:06:49.995  INFO 8868 --- [           main] o.s.b.c.r.s.JobRepositoryFactoryBean     : No database type set, using meta data indicating: MYSQL
2022-05-22 17:06:50.120  INFO 8868 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : No TaskExecutor has been set, defaulting to synchronous executor.
2022-05-22 17:06:50.230  INFO 8868 --- [           main] com.sunnier.batch.BatchApplication       : Started BatchApplication in 2.057 seconds (JVM running for 3.441)
2022-05-22 17:06:50.230  INFO 8868 --- [           main] o.s.b.a.b.JobLauncherApplicationRunner   : Running default command line with: [foo=5]
2022-05-22 17:06:50.380  INFO 8868 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=jobForExec]] launched with the following parameters: [{foo=5}]
2022-05-22 17:06:50.446  INFO 8868 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Executing step: [stepForExec]
I just save Ranking(rank=1, prev_rank=1, name=Manchester City, league=Barclays Premier League, off=2.9, def=0.2, spi=93.73)
I just save Ranking(rank=2, prev_rank=3, name=Liverpool, league=Barclays Premier League, off=2.92, def=0.25, spi=93.15)
I just save Ranking(rank=3, prev_rank=2, name=Bayern Munich, league=German Bundesliga, off=3.62, def=0.56, spi=93.01)
I just save Ranking(rank=4, prev_rank=4, name=Chelsea, league=Barclays Premier League, off=2.39, def=0.29, spi=88.69)
I just save Ranking(rank=5, prev_rank=6, name=Real Madrid, league=Spanish Primera Division, off=2.58, def=0.5, spi=86.63)
I just save Ranking(rank=6, prev_rank=5, name=Ajax, league=Dutch Eredivisie, off=3.02, def=0.74, spi=86.49)
I just save Ranking(rank=7, prev_rank=9, name=Barcelona, league=Spanish Primera Division, off=2.48, def=0.54, spi=84.77)
.
.
.
.
.
I just save Ranking(rank=640, prev_rank=640, name=Scunthorpe, league=English League Two, off=0.2, def=2.91, spi=3.73)
2022-05-22 17:06:56.440  INFO 8868 --- [           main] o.s.batch.core.step.AbstractStep         : Step: [stepForExec] executed in 5s991ms
2022-05-22 17:06:56.462  INFO 8868 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=jobForExec]] completed with the following parameters: [{foo=5}] and the following status: [COMPLETED] in 6s61ms
2022-05-22 17:06:56.468  INFO 8868 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2022-05-22 17:06:56.482  INFO 8868 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.
Disconnected from the target VM, address: '127.0.0.1:58171', transport: 'socket'

Process finished with exit code 0

메서드가 정상적으로 실행되었다.

끝.

 

====== 추가 =======
Service 에서 VO에 값을 조작할 수 있다.
RankingService 에서 VO 에 값을 넣고 출력해 보자.

@Service
public class RankingService {
    public void logRanking(Ranking rank) {
        System.out.println("I just save " + rank);
        rank.setName(rank.getName() + "__추가");
    }
}

Service에서 처리한 후에, DB에 update하는 writer도 만들어보자

    //update하는 Writer를 만든다.
    public JdbcBatchItemWriter<Ranking> updateItemWriter(){
        JdbcBatchItemWriter<Ranking> writer = new JdbcBatchItemWriter<Ranking>();
        writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<Ranking>());
        writer.setSql("update spi_global_rankings2 set   name = :name    where rank = :rank");
        writer.setDataSource(mariadbDataSource);
        writer.afterPropertiesSet();
        return writer;
    }

이제, compositeItemWriter로 순차처리한다.

    //컴포지트 ItemWriter를 만든다.
    @Bean
    public CompositeItemWriter compositeItemWriter() throws Exception {
        final CompositeItemWriter<Ranking> compositeItemWriter = new CompositeItemWriter<>();
        compositeItemWriter.setDelegates(Arrays.asList(
                jdbcBatchItemWriter(null),
                execItemWriter(null),
                printItemWriter(),
                updateItemWriter()
        ));
        return compositeItemWriter;
    }

출력하는 Writer로 만들자

    //Model을 출력하는 Writer를 만든다.
    public ItemWriter<Ranking> printItemWriter() throws Exception {
        return new ItemWriter<Ranking>() {
            @Override
            public void write(List<? extends Ranking> items) throws Exception {
                for (Ranking item : items){
                    System.out.println("rank =>" + item.getRank() + ", league => " + item.getLeague() + ", name=>" + item.getName());
                }
            }
        };
    }


실행하면,

2022-05-26 21:48:08.645  INFO 5700 --- [           main] o.s.b.a.b.JobLauncherApplicationRunner   : Running default command line with: [argu=foo131]
2022-05-26 21:48:08.723  INFO 5700 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=compositeJob]] launched with the following parameters: [{argu=foo131}]
2022-05-26 21:48:08.774  INFO 5700 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Executing step: [compositeStep]
I just save Ranking(rank=1, prev_rank=1, name=Manchester City, league=Barclays Premier League, off=2.9, def=0.2, spi=93.73)
rank =>1, league => Barclays Premier League, name=>Manchester City__추가
I just save Ranking(rank=2, prev_rank=3, name=Liverpool, league=Barclays Premier League, off=2.92, def=0.25, spi=93.15)
rank =>2, league => Barclays Premier League, name=>Liverpool__추가
I just save Ranking(rank=3, prev_rank=2, name=Bayern Munich, league=German Bundesliga, off=3.62, def=0.56, spi=93.01)
rank =>3, league => German Bundesliga, name=>Bayern Munich__추가

이렇게 VO의 값이 변경된다. 

요약하면,
1. DB에서 데이터를 읽고( JdbcPagingItemReader)
2. 결과를 처리한다(CompositeItemWriter)
   1) DB에 Insert 한다(JdbcBatchItemWriter)
   2) 서비스(메소드)를 호출한다(ItemWriterAdapter)  <= VO값을 조작/변경할 수 있다.
   3) VO값을 출력한다. (ItemWriter)
   4) 결과 데이터를 DB에 업데이트한다.(JdbcBatchItemWriter)

끝.