[JPA] fetch join

김형진·2023년 4월 28일

JPA에서 관리하는 Entity 객체 내의 참조 객체 필드는 기본적으로 Lazy 로딩으로 관리된다.
언제 어디서 객체 필드 참조가 필요할지 불분명하기 때문이다.

그렇다면 참조하는 객체가 필요할 때에는 그냥 접근하면 될까?
객체에 접근했을 때 참조 객체가 실제 객체가 아닌 Hibernate의 프록시 객체인 경우 알아서 DB에 한 번 더 쿼리를 날려 진짜 객체를 알아서 가져와준다.
편하긴 하겠지만, 참조 객체에 접근할 때마다 DB에 query가 한 번씩 더 나가기 때문에 성능이 저하된다는 문제점을 안고 있다.

이를 N+1문제라 하는데, 예를 들어 User객체를 먼저 조회해온 뒤, User가 참조하는 Team의 정보에 접근할 때 최대 유저의 수만큼 다시 Team을 조회하는 쿼리를 날려야 한다는 것이다. (물론 Team이 겹치는 User가 있는 경우 유저 수보다는 적은 쿼리를 날리게 될 것 이다.)
User가 Team뿐 아니라 다른 여러 객체를 참조하게 되면 최대 (유저 수 * 참조 객체) 만큼의 쿼리가 발생하게 된다.

그렇다면 이러한 경우 애초에 User가 참조하는 객체를 User조회 시 같이 가져오는 것이 성능에 더 나을 것이다.
그렇다고 함부로 LAZY로딩 설정을 풀 수는 없다.

이러한 경우 fetch join하는 쿼리를 보내는 로직을 하나 만들면 된다.
fetch join은 DB의 join과 같으며 jpa에서 사용하는 문법이다.
fetch join으로 원하는 테이블에 미리 join하여 원하는 객체의 정보를 User와 함께 담아오면 끝

그냥 join을 사용하면 안되는 이유는, 그냥 join을 사용해도 실제로 영속화되는건 주체가 되는 Entity, 즉 이 경우에는 User만 영속화되므로 Team의 데이터를 쓸 수 없다.
따라서 그냥 Join은 참조 객체를 검색조건으로 사용할 때만 거의 사용되며 실제로 참조객체의 데이터를 사용하기 위해서는 대상 객체를 영속화시켜주는 fetch join을 사용해야 한다.

profile
히히

0개의 댓글