process와 writer를 끝난 데이터는 ChunkOrientedTasklet을 따라 반환되고 TaskletStep의 doExecute에 오게된다.
더 반환해보면 chunkContext.isComplete를 확인하고 true가 아니면 attributeQueue에 다시 넣어준다.
이 attributeQueue가 뭐냐면,
ItemReader는 RepeatTemplate의 executeInternal메소드를 타게된다.
여기에 getNextResult를 들고오는데
띠용 여기에 떡하니 attributeQueue에서 가지고온다. 여기서 다음 처리할게 있는지 확인하는것으로 보인다.
이 모든 과정을 다 거치고 나면 다시 TaskletStep 의 하기 로직을 탄다.
이 로직이 바로 Reader를 읽어오는 과정이다.
여기서 ChunkOrientedTasklet으로 Reader를 반복한다.
더 밑으로 내려가다 이 코드가 보인다.
getNextResult에서 result를 받아온 후,isComplete에서 ItemReader에서 받아온 값을 기반으로 더 반복할지 말지 정하고있다.
내가 사용하는 MyBatisPagingItemReader에서 어떻게 isComplete를 정하는지 파봐야한다.
MyBatisPagingItemReader는 이름에서 보듯 Paging 단위로 처리가 된다. 하기 파라미터를 통해 페이징을 구현할 수 있다.
_page : 읽을 page 수량 (0부터 시작)
_pagesize : 한번에 읽을 페이지 수량 (리턴 받을 데이터의 수량)
_skiprows : _page * _pagesize (다음 페이지 시작 포인트, offset)
[사용법]
<select id="exampleselect">
SELECT id, name, job FROM MEMBER ORDER BY id ASC
OFFSET #{_skiprows} LIMIT #{_pagesize}
</select>
MyBatisPagingItemReader.java
본격적으로 이 클래스를 들여다 보면 파라미터를 셋팅해주고 ArrayList인 result에 받아온 queryId와 parameters로 selectList를 실행한다.
여기서 무한 반복 이슈의 원인을 알 수 있었다. 내가 설정한 쿼리에는 paging 처리가 따로 없었다.
구글링에서 자동으로 계산해준다는게 파라미터 설정이 없어도 자동이란 뜻은 아니였다.(파라미터 설정 필수!)
select * from example와 같다면 무한 반복할 수 밖에 없다.
paging 설정을 적절하게 해주니 무한 반복이슈를 해결할 수 있었다.
처음 구현했을때 paging을 쓰지않고 예제를 따라 붙이는 식으로 진행하다가 paging을 발견하고 겉핥기로 본 후 무작정 사용해본게 문제였다.
역시 뭐하나 허투루 넘어가지 말아야겠다.