티스토리 뷰

반응형

SQL 출력문을 반드시 확인하자.

JPA에 익숙하지 않을때는 아무래도 구현하는 것에 더 집중하면서 실제 SQL 쿼리문이 어떤식으로 나오게 되는지 유심히 보지 못한 것이 사실이다. 이번 프로젝트에는 꼼꼼히 볼려고 노력해봤는데 SQL문을 확인해면 크게 2가지 문제가 있었다.

 

문제 1. 불필요한 Outer Join (optional 속성을 반드시 명시하자)

관계를 맞는 엔티티간의 관계가 반드시 존재하는지, 혹은 선택적인지에 따라 실제 두 테이블(도메인)을 조인하는 전략이 달라지는데, 만약 관계가 반드시 존재한다면 (= 테이블상의 FK가 반드시 존재한다면), optional 속성을 통해서 이를 명시해야한다. 그렇지 않다면 null인 경우도 대비해야 하기 떄문에 outer join이 발생한다.

 

@ManyToOne에 optional 속성을 별개로 명시하지 않으면,
left outer join이 일어난다.

 

optional = false 로 두면

 

join 문이 아예 사라졌다! (실제로 join이 필요한 상황에서도 inner join으로 바뀜)

 

 

(+ 추가적으로 @JoinColumn 속성에 nullable = false로 주는 방법도 있지만, FK를 where절에서 이용하는 경우는 Outer Join이 없어지지 않았다. optional로 명시하는 경우는 Outer Join이 없어졌다.)

 

문제 2. 1+N (N+1) 문제 (fetch join을 사용해야 하는 경우를 미리 대비하자.)

(Fetch Type을 LAZY로 두는 경우가 많아) 쿼리메소드를 남발하면 1+N문제가 빈번하게 발생했다. (강사님이 왜 자동 생성되는 쿼리 메소드 보다, JPQL을 직접 선언하라고 하신지 이제야 알 것 같다..) JPQL을 직접 선언하고 fetch join을 명시하여서 해결하였다.

findAll을 그냥 사용하지 말고 JOIN FETCH를 선언하는 방식으로 오버라이딩~!

 

문제 3. (FETCH JOIN 사용시에 파생되는) 카테시안 곱 문제 

패치조인을 사용하게 되면, '카테시안 곱'문제가 발생하여서 실제 존재하는 데이터 수보다 더 많은 데이터를 가져오는 경우가 있다. 예를들어 Book 이 3건이 있고, 연관된 Chapter가 5건 있을 때, Book을 모두 조회하면 3건만 나와야 하지만 3x5 = 15건이 조회된다.

 

이 경우에 Set 자료구조를 사용하거나 List를 사용하고 싶다면 DISTINCT를 쿼리문에 명시하자.

 

반응형
댓글