일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- TCP/IP
- DI
- Javascript
- 공짜로 Docker Desktop같은거 쓰기
- mock stub spy
- frontend
- Spock Stub
- webpack
- nuxtjs/composition-api buildModules
- 자바스크립트
- HTTP란
- docker desktop 유료화 정책
- enum
- TypeScript
- Mock vs Stub
- @Transaction propagation
- 트랜잭션 격리
- 타입스크립트
- docker desktop 대체
- Vue+Typescript
- Spock Spy
- 의존성주입
- Spock Mock
- Docker Desktop 쓰고싶다
- vue store
- mock stub
- @Transaction isolation
- Spock Mock Stub Spy
- ECMAScript
- Rancher Desktop설치
- Today
- Total
끄적끄적
[SPRING + JPA] QueryDsl FetchJoin 본문
최근 생각도 못했던 문제가 있어 또 한번 고생한 경험이 있다.
JPA를 쓰는 환경에서는 대체로 아래와 같이 릴레이션에 대한 조인을 걸어두고 쓰는 경우가 많을 것이다.
queryDsl로 리스트를 만들어주는 부분에서 조인걸린 테이블에 대한 조건처리를 해야할 경우가 생겼다.
왜 여태까지 이런 경우가 많이 없었는지 이해가 안되지만..
또 한번의 삽질이 시작되었다. queryDsl에 조인을 걸고 조인걸린 부분에 대한 조건을 추가하고 확인해본결과
이상한 데이터가 자꾸 포함되어 조회가 되는것이였다. 로그에 남겨진 쿼리를 모두 분석하기 시작했다..
쿼리가 나뉘어서 날라가면서 발생한 문제였다. 부모 테이블에서 조건처리에 대한 부분을 필터링 한 다음에 id를 기반으로 다시 IN을 하는것이다.
튜닝을 위해 찾아보기 시작했다.
fetchJoin.. 연관된 엔티티 or 컬렉션을 SQL 한번에 함께 조회하는 기능이 있다는 문구를 봤다.
그래서 아래와 같이 튜닝했다.
factory.selectFrom(exampleOrm)
.join(exampleOrm.examplePeriodOrmList, examplePeriodOrm)
.fetchJoin()
.where(where)
.orderBy(exampleOrm.createdAt.desc())
.offset(offset)
.limit(request.getSize())
.distinct();
작성 후 런.. 로그를 보던중에 이상한걸 발견
HHH000104: firstResult/maxResults specified with collection fetch; applying in memory!
!? 이게 뭐지 확인해보니
fetch join 과 pagination 을 같이 할 시
"모든 데이터"를 전부 가져와 메모리에서 걸러낸다는 것이다.
이건 좀 아니다 싶었다. 그래서 다시 리펙토링..
limit과 offset,orderby부분만 다르게 처리하면 되는 것 같았다.
List<Long> ids = factory.select(exampleOrm.id)
.from(exampleOrm)
.join(exampleOrm.examplePeriodOrmList, examplePeriodOrm)
.fetchJoin()
.where(where)
.offset(offset)
.limit(request.getSize())
.fetch();
List<ExampleOrm> list = factory.selectFrom(exampleOrm)
.join(exampleOrm.examplePeriodOrmList, examplePeriodOrm)
.fetchJoin()
.where(exampleOrm.id.in(ids))
.where(where)
.orderBy(exampleOrm.createdAt.desc())
.fetch();
// 총 카운트
Long count = factory
.select(Wildcard.count)
.from(exampleOrm)
.where(where)
.fetch()
.get(0);
result = new QueryResults<PolicyOrm>(list, Long.valueOf(request.getSize()), Long.valueOf(offset), count);
위와같이 id 리스트를 먼저 얻은 뒤 이후에 in절로 필요한 부분만 처리한 후 런..해보니 없어졌다.
테스트코드를 돌려보니 잘된다. fetchJoin을 사용할 때 앞으로 조심해야 할 듯 하다.
'Back-end > Java' 카테고리의 다른 글
[JUNIT] Mock Test 작성요령 (0) | 2021.12.07 |
---|---|
[JUNIT] Intellij Junit Test 실패 No tests found for given includes 에러 해결방법 (0) | 2021.11.29 |
[JAVA] JavaTimeModule 포멧팅 (0) | 2021.11.12 |
[JAVA] Enum 삽질기.. (1) | 2021.11.11 |
[JAVA] Spring Boot json Enum json object or jsonvalue (0) | 2021.11.10 |