Spring Batch7 - Batch ItemReader , Itemprocessor , ItemWriter
포스트
취소

Spring Batch7 - Batch ItemReader , Itemprocessor , ItemWriter

Tasklet VS ItemReader , Itemprocessor , ItemWriter

오늘부터는 ItemReader , ItemProcessor , ItemWriter 에 대해서 공부를 할 것입니다 앞전까지는 우리는 Tasklet 을 step 에 등록을 해서 job 을 진행을 시켰다면 이제부터는 데이터를 읽고 , 가공하고 , 다시 쓰는 방식인 ItemReader , ItemProcessor , ItemWriter 을 공부할것입니다 그 전에 우리는 사전작업을 할것인데 간단한 쇼핑몰 ERD 구축후 진행을 하겠습니다

ERD

ERD

ERD 간단하게 만들어줄것입니다

ERD 스크립트 (mysql)

CREATE TABLE Users ( UserID INT NOT NULL AUTO_INCREMENT, UserName VARCHAR(100) , PRIMARY KEY(UserID) );

CREATE TABLE Items ( ItemId INT NOT NULL AUTO_INCREMENT, ItemName VARCHAR(100) , ItemType VARCHAR(100) , ItemPrice INT, PRIMARY KEY(ItemId) );

CREATE TABLE Purchases ( PurchaseId VARCHAR(100) NOT NULL, UserID INT, ItemId INT, PurchaseIdDts DATE, PRIMARY KEY(PurchaseId) );

CREATE TABLE Calculates ( CalculateId varchar(100) NOT NULL , UserId INT, UserName Varchar(100), ItemId INT, ItemName Varchar(100), ItemType Varchar(100), ItemPrice INT, PurchaseId Varchar(100), PurchaseIdDts DATE,

PRIMARY KEY(CalculateId) );

기초 데이터 스크립트

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
INSERT INTO Users(UserName) values('KIM');
INSERT INTO Users(UserName) values('LEE');
INSERT INTO Users(UserName) values('TIME');
INSERT INTO Users(UserName) values('HEO');
INSERT INTO Users(UserName) values('BEAN');


INSERT INTO Items(ItemName , ItemType , ItemPrice) values('수박' 		, '과일' , '1000');
INSERT INTO Items(ItemName , ItemType , ItemPrice) values('오렌지' 	, '과일' , '1500');
INSERT INTO Items(ItemName , ItemType , ItemPrice) values('청포도' 	, '과일' , '1700');
INSERT INTO Items(ItemName , ItemType , ItemPrice) values('포도' 		, '과일' , '2000');
INSERT INTO Items(ItemName , ItemType , ItemPrice) values('딸기' 		, '과일' , '2300');

INSERT INTO Items(ItemName , ItemType , ItemPrice) values('java 100일 문법' 			, '책' , '5000');
INSERT INTO Items(ItemName , ItemType , ItemPrice) values('oracle 100일 문법' 		, '책' , '6000');
INSERT INTO Items(ItemName , ItemType , ItemPrice) values('spring 이주일만에  끝내기' 	, '책' , '13000');
INSERT INTO Items(ItemName , ItemType , ItemPrice) values('보안이란 무엇인가' 			, '책' , '20000');
INSERT INTO Items(ItemName , ItemType , ItemPrice) values('알고리즘 입문' 				, '책' , '50000');

INSERT INTO Items(ItemName , ItemType , ItemPrice) values('돼지 삼겹살' 	, '육류' , '25000');
INSERT INTO Items(ItemName , ItemType , ItemPrice) values('돼지 목살' 		, '육류' , '27000');
INSERT INTO Items(ItemName , ItemType , ItemPrice) values('한우 등심' 		, '육류' , '57000');
INSERT INTO Items(ItemName , ItemType , ItemPrice) values('닭고기 7호' 	, '육류' , '19800');
INSERT INTO Items(ItemName , ItemType , ItemPrice) values('닭고기 8호' 	, '육류' , '25000');

INSERT INTO Items(ItemName , ItemType , ItemPrice) values('닭강정' 	, 'PB제품' , '9900');
INSERT INTO Items(ItemName , ItemType , ItemPrice) values('옛날통닭' 	, 'PB제품' , '19900');
INSERT INTO Items(ItemName , ItemType , ItemPrice) values('훈제삼겹살' , 'PB제품' , '29900');
INSERT INTO Items(ItemName , ItemType , ItemPrice) values('훈제오리'  , 'PB제품' , '25000');

INSERT INTO Items(ItemName , ItemType , ItemPrice) values('비비고냉동만두'  , '냉동식품' , '6000');
INSERT INTO Items(ItemName , ItemType , ItemPrice) values('고향만두'  		, '냉동식품' , '7000');
INSERT INTO Items(ItemName , ItemType , ItemPrice) values('풀무원물만두'  	, '냉동식품' , '9000');
INSERT INTO Items(ItemName , ItemType , ItemPrice) values('오뚜기OX만두'  	, '냉동식품' , '8000');

INSERT INTO Items(ItemName , ItemType , ItemPrice) values('오뚜기진라면매운맛'  	, '라면' , '990');
INSERT INTO Items(ItemName , ItemType , ItemPrice) values('오뚜기진라면순한맛'  	, '라면' , '890');
INSERT INTO Items(ItemName , ItemType , ItemPrice) values('신라면'  			, '라면' , '1100');
INSERT INTO Items(ItemName , ItemType , ItemPrice) values('신라면레드'  		, '라면' , '1250');
INSERT INTO Items(ItemName , ItemType , ItemPrice) values('팔도비민면'  		, '라면' , '980');

INSERT INTO Items(ItemName , ItemType , ItemPrice) values('코카콜라'  		, '주류' , '600');
INSERT INTO Items(ItemName , ItemType , ItemPrice) values('펩시'  		, '주류' , '1100');
INSERT INTO Items(ItemName , ItemType , ItemPrice) values('칠성사이다'  	, '주류' , '1200');
INSERT INTO Items(ItemName , ItemType , ItemPrice) values('솔의눈'  		, '주류' , '1500');
INSERT INTO Items(ItemName , ItemType , ItemPrice) values('밀키스'  		, '주류' , '1300');


시나리오

총 5명의 사람이 금일 무작위로 물풀을 구매할 예정입니다 구매가 끝나면 해당내역을 정산 테이블로 이관하여서 구매 = 정산의 데이터가 올바른지 확인을 하는 시나리오를 만들것입니다

사전작업 코드 (GitLab 주소 첨부)

https://gitlab.com/kimdongy1000/spring-batch/-/tree/main/src/main/java/com/example/demo/batch/shpping?ref_type=heads 해당 git 은 민감정보 (application.yml 을 제외한 모든 소스코드파일입니다)

실행시

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
32
33
34
35
36
37
38
39
Users{userID=1, userName='KIM'}
Users{userID=2, userName='LEE'}
Users{userID=3, userName='TIME'}
Users{userID=4, userName='HEO'}
Users{userID=5, userName='BEAN'}
Items{itemId=1, itemName='수박', itemType='과일', itemPrice=1000}
Items{itemId=2, itemName='오렌지', itemType='과일', itemPrice=1500}
Items{itemId=3, itemName='청포도', itemType='과일', itemPrice=1700}
Items{itemId=4, itemName='포도', itemType='과일', itemPrice=2000}
Items{itemId=5, itemName='딸기', itemType='과일', itemPrice=2300}
Items{itemId=6, itemName='java 100일 문법', itemType='책', itemPrice=5000}
Items{itemId=7, itemName='oracle 100일 문법', itemType='책', itemPrice=6000}
Items{itemId=8, itemName='spring 이주일만에  끝내기', itemType='책', itemPrice=13000}
Items{itemId=9, itemName='보안이란 무엇인가', itemType='책', itemPrice=20000}
Items{itemId=10, itemName='알고리즘 입문', itemType='책', itemPrice=50000}
Items{itemId=11, itemName='돼지 삼겹살', itemType='육류', itemPrice=25000}
Items{itemId=12, itemName='돼지 목살', itemType='육류', itemPrice=27000}
Items{itemId=13, itemName='한우 등심', itemType='육류', itemPrice=57000}
Items{itemId=14, itemName='닭고기 7호', itemType='육류', itemPrice=19800}
Items{itemId=15, itemName='닭고기 8호', itemType='육류', itemPrice=25000}
Items{itemId=16, itemName='닭강정', itemType='PB제품', itemPrice=9900}
Items{itemId=17, itemName='옛날통닭', itemType='PB제품', itemPrice=19900}
Items{itemId=18, itemName='훈제삼겹살', itemType='PB제품', itemPrice=29900}
Items{itemId=19, itemName='훈제오리', itemType='PB제품', itemPrice=25000}
Items{itemId=20, itemName='비비고냉동만두', itemType='냉동식품', itemPrice=6000}
Items{itemId=21, itemName='고향만두', itemType='냉동식품', itemPrice=7000}
Items{itemId=22, itemName='풀무원물만두', itemType='냉동식품', itemPrice=9000}
Items{itemId=23, itemName='오뚜기OX만두', itemType='냉동식품', itemPrice=8000}
Items{itemId=24, itemName='오뚜기진라면매운맛', itemType='라면', itemPrice=990}
Items{itemId=25, itemName='오뚜기진라면순한맛', itemType='라면', itemPrice=890}
Items{itemId=26, itemName='신라면', itemType='라면', itemPrice=1100}
Items{itemId=27, itemName='신라면레드', itemType='라면', itemPrice=1250}
Items{itemId=28, itemName='팔도비민면', itemType='라면', itemPrice=980}
Items{itemId=29, itemName='코카콜라', itemType='주류', itemPrice=600}
Items{itemId=30, itemName='펩시', itemType='주류', itemPrice=1100}
Items{itemId=31, itemName='칠성사이다', itemType='주류', itemPrice=1200}
Items{itemId=32, itemName='솔의눈', itemType='주류', itemPrice=1500}
Items{itemId=33, itemName='밀키스', itemType='주류', itemPrice=1300}

이렇게 저장이 출력이 되면 올바르게 된것입니다

무작위 쇼핑진행

이제 등록된 사람들이 무작위로 쇼핑을 즐길것입니다 이때 우리는 이 데이터들을 Purchases 넣을것인데

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
@Configuration
@RequiredArgsConstructor
public class ShoppingBatchJob {

    @Autowired
    private JobBuilderFactory jobBuilderFactory;

    @Autowired
    private StepBuilderFactory stepBuilderFactory;

    @Autowired
    private PurchasesJpaRepository purchasesRepository;

    @Autowired
    private final List<Users> users;

    @Autowired
    private final List<Items> items;



    @Bean
    public Job shoppingJob(Step shoppingStep1){

        return jobBuilderFactory.get("shoppingJob")
                .incrementer(new RunIdIncrementer())
                .start(shoppingStep1)
                .build();
    }

    @Bean
    @JobScope
    public Step shoppingStep1(){

        return stepBuilderFactory.get("shoppingStep1")
                .tasklet(new Tasklet() {
                    @Override
                    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {

                        Random userRnd = new Random();
                        Random itemRnd = new Random();


                        List<Purchases> purchasesList = new ArrayList<>();
                        String todayFormat = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));


                        for (int i = 0; i < 10000; i++) {

                            int user_rndNumber = userRnd.nextInt(4);
                            int item_rndNumber = itemRnd.nextInt(32);

                            Users rndUser = users.get(user_rndNumber);
                            Items rndItems = items.get(item_rndNumber);

                            purchasesList.add(new Purchases(todayFormat +"_"+ UUID.randomUUID().toString()  , rndUser.getUserID() , rndItems.getItemId() ,  new Date()));

                        }

                       purchasesRepository.saveAll(purchasesList);


                        return RepeatStatus.FINISHED;
                    }


                }).build();

    }
}

shoppingStep1 을 잘보시면 for 문을 통해서 무작위 경우 1만번을 실행시켜서 최종 1만번의 쇼핑을 시킵니다 그리고 그 결과를 list 에 담아두고 그 리스트를 save 하면됩니다 그러면 DB 데이터를 보게 되면

ERD

이렇게 무작위 데이터 1만개가 들어와 있는모습을 알 수 있습니다 여기 까지가 사전작업 이제 본 작업 실행하겠습니다 본작업은 다음장에서 진행을 하겠습니다