티스토리 뷰
spring batch 4.3 부터 JpaCursorItemReader 가 추가됐다. 이게 추가되기 이전에는 배치에서 JPA 를 쓸땐 JpaPagingItemReader 를 사용하거나 cursor 방식이 필요하다면 HibernateCursorItemReader 를 써야했다.
JpaCursorItemReader 가 추가된지 비교적 얼마 안됐기때문에 아직 HibernateCursorItemReader 를 이용해 돌아가고있는 배치가 많을 것으로 예상한다. 하지만 HibernateCursorItemReader 는 spring batch 5.0 부터 Deprecate 되었고, 5.2 부터는 아예 삭제될 예정이므로 최신 spring batch 에서 배치 로직을 작성하거나 기존 spring batch 프로젝트의 버전업을 고려하고있다면 HibernateCursorItemReader 를 사용할 수 없다. 아래는 HibernateCursorItemReader 의 javadoc 에서 가져온 내용이다.
Deprecated, for removal: This API element is subject to removal in a future version.
since 5.0 for removal in 5.2. Use the JpaCursorItemReader instead.
HibernateCursorItemReader 대신에 JpaCursorItemReader 를 사용하라고 하고있다.
그럼 JPA 가 등장한건 오래됐는데 JpaCursorItemReader 는 왜이리 늦게 나온걸까? JPA 자체 스펙에 stream 스펙이 비교적 최근에 추가됐기 때문이다.( https://thorben-janssen.com/whats-new-in-jpa-2-2/#stream-query-results )
이전에는 JPA 스펙으로 스트리밍을 지원하지 않았기 때문에 JPA 로 대량의 데이터를 처리하기 위해서는 오로지 페이징 기법만 사용해야했고, Hibernate 는 JPA 와 별개로 스트리밍처리를 지원했기에 HibernateCursorItemReader 만 존재했던 것이다.
그럼 JpaCursorItemReader 는 어떤 방식으로 스트리밍 처리를 지원할까? 일단 spring batch 가 제공하는 ItemReader 를 살펴보기전에 JPA 에 추가된 인터페이스를 살펴보자
해당 코드를 살펴보면 Stream 을 리턴하는 메서드가 디폴트 메서드로 추가되어있다.( https://github.com/jakartaee/persistence/blob/a3138b1d1a7f5d37eada7cc9d9f8aa36e818e09c/api/src/main/java/jakarta/persistence/Query.java#L95 )
default Stream getResultStream() {
return getResultList().stream();
}
즉 이 디폴트 구현을 그대로 쓰면 스트리밍의 이점을 전혀 살릴 수 없다. 애플리케이션 단에서 getResultList() 로 조회결과를 모두 메모리에 올리고 그걸 그냥 스트리밍 처리하는 방식이기 때문이다. Hibernate 는 JPA 의 이 스펙을 구현하면서 기존부터 스트리밍을 처리하고있던 stream() 메서드를 이용하고있다. JPA 와 독자스펙으로 처리하고 있던걸 JPA 를 오버라이딩하면서 기존 코드를 내부적으로 이용하도록 하는 것이다. 그리고 결과적으로 이 스펙은 JDBC 를 이용해서 스트리밍을 처리하게 된다.
그리고 spring batch 의 JpaCursorItemReader 는 이러한 JPA 의 getResultStream() 을 활용하는 것인데 이렇다면 결국 최종 내부 구현은 JdbcCursorItemReader 나 JpaCursorItemReader 나 같은 메커니즘으로 도는것이다. 자바의 데이터베이스 표준이 JDBC 이고, ORM 역시 JDBC 에 기초해서 추상화를 제공하고있는 것이니 당연한 일일 것이다.
JPA 스펙에 추가된 getResultStream() 의 디폴트 메서드는 인터페이스 확장을 위한 기본 구현일 뿐이다. 이를 Hibernate 와 같은 각 JPA 구현체에서 제대로 오버라이딩해주지 않는다면 스트리밍의 역할을 하지 못하겠지만 이상한 구현체를 사용하는게 아닌 이상은 제대로 오버라이딩해서 스트리밍 처리를 잘 지원해주고 있다. 그리고 이를 기반으로 하고있는 JpaCursorItemReader 도 옵션을 잘 지정해서 사용한다면 기존 HibernateCursorItemReader, JdbcCursorItemReader 를 사용하는 것과 같은 이점을 누릴 수 있다.
참고로 JpaCursorItemReader 는 Jdbc, Hibernate 구현체와 달리 fetchSize 를 조절하는 옵션이 없다. 이는 구현체에 누락된 사항으로 spring batch 5.2 에서 옵션이 추가될 것으로 보인다.( https://github.com/spring-projects/spring-batch/issues/4479 )
# 참고자료
- https://vladmihalcea.com/whats-new-in-jpa-2-2-stream-the-result-of-a-query-execution/
- https://thorben-janssen.com/jpa-2-2s-new-stream-method-and-how-you-should-not-use-it/
'Java > batch' 카테고리의 다른 글
CursorItemReader 를 이용할때 어떤 timeout 을 조절해야할까 (0) | 2024.11.08 |
---|---|
spring batch 에서 사라진 JobBuilderFactory (0) | 2024.05.15 |
Spring batch 테스트하기 (1) | 2022.05.28 |
JdbcPagingItemReader 에서 column not found (0) | 2021.08.28 |
spring-batch 에서 TaskExecutor 사용시 jvm 종료 안 되는 현상 (1) | 2021.05.02 |
- Total
- Today
- Yesterday
- Git
- OOP
- javascript
- code
- Design Pattern
- frontend개발환경
- spring cloud
- clean code
- http
- Kotlin
- backend개발환경
- java
- Jackson
- JPA
- 정규표현식
- mariadb
- java8
- DesignPattern
- generics
- TEST
- go-core
- MySQL
- frontcode
- toby
- db
- EffectiveJava
- programming
- JavaScript Core
- servlet
- Spring
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |