두리공장
[Spring batch] Step 6 - DB를 읽어서 서비스 Method 호출하기 본문
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)
끝.
'java' 카테고리의 다른 글
[Spring batch] Step 8 - 2개이상 write 작업수행을 위해 CompositeItemWriter를 사용하자 (데이터 출력을 위한 CustomItemWriter 작성 포함) (0) | 2022.05.26 |
---|---|
[Spring batch] Step 7 - Multi DataSource 사용하기 (0) | 2022.05.24 |
[Spring batch] Step 5 - DB를 읽어서 DB에 저장하기 (0) | 2022.03.24 |
[Spring batch] Step 3 - CSV 파일을 읽어서 DB에 저장하기 (0) | 2022.03.21 |
[Spring batch] Step 2 - CSV 파일을 읽어서 출력하기 (0) | 2022.03.21 |