[Querydsl] fetch join으로 n+1 문제 피하기

by 스뎅(thDeng) on

Querydsl로 select를 할 때 innerJoin()이나 leftJoin(), rightJoin() 등을 사용하면 from()에 있는 entity만 꺼내진다. join된 테이블이 select의 조건으로만 쓰고 실제 데이터는 필요가 없다면, 이런 join들을 사용하면 된다.

하지만 함께 join된 테이블의 값을 같이 꺼내고 싶은 경우, 다시 select를 해야 하는 n+1 문제가 발생할 수 있다. 이럴 때 fetchJoin을 사용하면 한번에 꺼내온다.

innerJoin, leftJoin, rightJoin

  public List<User> findMe(String street) {
      return from(QUser.user)
          .leftJoin(QUser.user.addresses, QAddress.address)
          .where(QAddress.address.street.eq(street))
          .fetch();
  }

아래처럼 address가 where절에 조건이 들어가지만 select 대상에는 없는 것을 볼 수 있다.

select
    user0_.id as id1_10_,
    user0_.username as username2_10_
from
    user user0_
left outer join
    address addresses1_
        on user0_.id=addresses1_.user_id
where
    addresses1_.street=?

fetchJoin

  public List<User> findMe(String street) {
      return from(QUser.user)
          .leftJoin(QUser.user.addresses, QAddress.address)
          .fetchJoin()
          .where(QAddress.address.street.eq(street))
          .fetch();
  }

fetchJoin을 사용하면 address가 select 대상에도 포함된다.

select
    user0_.id as id1_10_0_,
    addresses1_.id as id1_5_1_,
    user0_.username as username2_10_0_,
    addresses1_.street as street2_5_1_,
    addresses1_.user_id as user_id3_5_0__,
    addresses1_.id as id1_5_0__
from
    user user0_
left outer join
    address addresses1_
        on user0_.id=addresses1_.user_id
where
    addresses1_.street=?
별도로 명시하지 않을 경우, 이 블로그의 포스트는 다음 라이선스에 따라 사용할 수 있습니다: Creative Commons License CC Attribution-NonCommercial-ShareAlike 4.0 International License