inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

스프링 배치

Repositoryitemreader로 조회한 데이터 dirty check 여부 질문

986

jungkh405

작성한 질문수 6

0

안녕하세요~ 강사님 강의를 보고 스프링 배치 입문해서 열심히 이론부터 실습까지 잘 배우고 있습니다.
몇 가지 궁금한 점이 있어서 이렇게 질문을 드리게 되었습니다.

1.

ItemReader 중에 Repositoryitemreader라는 구현체가 있어서 이게 Spring Data JPA를 지원해 줘서 사용해 보았는데요. 이해가 가지 않는 부분이 있어서 질문드리고자 합니다.

    @Bean(name = STEP_NAME)
    @JobScope
    public Step step1(@Value("#{jobParameters[chunkSize]}") Long chunkSize) {
        return stepBuilderFactory.get(STEP_NAME)
                .<HistoryEntity, HistoryEntity>chunk(chunkSize.intValue())
                .reader(itemReader(null))
                .processor(itemProcessor())
                .writer(itemWriter())
                .build();
    }

  @Bean(name = JOB_NAME + "_reader")
    @StepScope
    public RepositoryItemReader<HistoryEntity> itemReader(@Value("#{jobParameters[chunkSize]}") Long chunkSize) {

        LocalDateTime now = LocalDateTime.now();

        return new RepositoryItemReaderBuilder<HistoryEntity>()
                .name(JOB_NAME + "_reader")
                .repository(HistoryPagingCrudRepository)
                .methodName("findByLeaveDtLessThanEqual")
                .pageSize(chunkSize.intValue())
                .arguments(List.of(now))
                .sorts(Collections.singletonMap("leaveDt", Sort.Direction.DESC))
                .build();
    }

위와 같은 step과 특정 날짜의 데이터를 조회하는 ItemReader를 구현한 후 아래 ItemWriter 에서

 @Bean(name = JOB_NAME + "_writer")
    @StepScope
    public ItemWriter<HistoryEntity> itemWriter() {

        return item -> {
            item.forEach(historyEntity -> {
                       // Id 값을 null로 만드는 메소드
                       historyEntity.updateRemoveId(); 
                    }
            );
        };
    }

Entity의 값을 변경하게 되면 당연히 하나의 chunk 단위에서는 하나의 트랜잭션 이기 때문에 JPA의 dirty check로 인한 Id 값을 지우는 update 쿼리가 나갈거라고 생각했는데 그렇지 않더라고요.

다만,

 @Bean(name = JOB_NAME + "_writer")
    @StepScope
    public ItemWriter<HistoryEntity> itemWriter() {

        return item -> {
            item.forEach(historyEntity -> {
                       // Id 값을 null로 만드는 메소드
                       historyEntity.updateRemoveId(); 
                       historyPagingCrudRepository.save(historyEntity) 
                    }
            );
        };
    }

위 코드 historyPagingCrudRepository.save(historyEntity) 를 추가하면 merge가 진행되면서 update 쿼리가 실행되긴 하지만 select 쿼리가 한 번 더 실행돼서 비효율적인거 같다는 생각이 들었습니다.

질문을 정리하자면 ItemReader에서 조회한 Entity가 ItemWriter에서도 영속 상태이기 때문에 Dirty Checking 대상이라고 생각했는데 그렇지 않은 이유가 무엇인가요??

혹시 ItemReader 로 데이터 조회 후 ChunkProvider를 통해 Chunk<I> 를 itemProcessor 또는 ItemWriter로 전달하는 과정에서 준영속 상태가 되는것일까요??

 

 

2.

jpaPagingItemReader 으로 데이터 조회 후, ItemWriter 에서 jpaPagingItemReader 의 where 절에 해당하는 컬럼의 값을 수정했을 때 offset(page)로 인해 일부 데이터가 읽히지 않는 문제가 있는것으로 알고있습니다. 이 경우 getPage() 메소드를 override 해서 항상 offset을 0으로 고정시키는 방법으로 해결이 가능한데 Repositoryitemreader 구현체 사용 시 어떤식으로 해결이 가능할까요??

spring-boot spring-batch

답변 1

0

정수원

일단 제가 Repositoryitemreader 를 사용해 보지 못해서 정확한 원인은 테스트 해 봐야 될 것 같습니다

일반적으로 JPA 로 배치 처리를 할 경우 JPA 용 트랜잭션이 기본적으로 작동하기 때문에 영속상태가 유지되는 것은 맞습니다

영속 상태 유지는 트랜잭션 안에서 가능한고 더티체킹 반영은 쓰기 지연 SQL 항목들이 트랜잭션이 커밋되는 시점에 이루어지기 때문에 이 두가지가 제대로 처리되고 있는지를 확인해 봐야 합니다

또한 ItemReader 와 ItemWriter 에서 사용하는 EntityManager 가 동일한 트랜잭션을 계속 타고 있는지도 봐야 합니다

제가 보기에는 ItemWriter 로 넘어온 엔터티가 계속 영속상태인지 명확하지 않는 것 같습니다

즉 Repositoryitemreader 의 영속상태가 초기화가 된 것 같습니다

2번 질문은 Repositoryitemreader 를 사용해 봐야 알 것 같습니다

깃 소스 공유 가능하시면 제가 테스트 해 보도록 하겠습니다

 

스프링 배치 버전 질문

0

126

1

소스코드가 어디에 있나요?

0

100

2

트랜잭션 예외

0

92

1

질문이 있습니다.

0

131

2

ChunkListener 에서 beforeChunk 의 실행 시점 관련 질문

0

127

2

여러 JOB 설정하는법

0

152

2

강의 자료 다른 방법 있을까요?

0

157

1

JobExecution과 JobExecutionContext와의 관계

0

190

2

특정 job만 실행

1

257

1

Batch 성능 질문

0

153

1

ItemReaderAdapter 종료

0

81

1

[ 강좌 Git 브랜치 문의 ] 섹션 9 > JdbcCursorItemReader, JpaCursorItemReader

0

179

2

Spring Batch 배포 질문

0

246

2

spring batch 버전

0

236

2

retry count 관련 질문

0

174

2

StepExecutionListener 의 afterStep 에서 return ExitStatus.FAILED 에 의한 동작에 의문이 갑니다.

0

332

2

jdbc, jpa 커서방식 조회 방식 차이 질문 (강사님께 답변 받고 싶습니다)

0

235

2

Multithread step과 AsyncItemProcessor

0

203

2

job 재실행

0

253

2

bean 생명주기 문제 도와주세요(@Scope("step"), @Autowired)

0

183

1

Multi-threaded-step과 Partitioning 차이 확인

0

178

2

jdbcCursorReader, jdbcPagingReader 질문

0

146

1

step muti-thread 질문

0

111

1

itemSteam open update close 질문

0

113

1