[Spring boot] Querydsl JOIN

전수·2023년 11월 6일
0

Spring

목록 보기
13/13

JOIN

JOIN이란 여러 테이블의 레코드를 조합하여 하나의 열로 표현한 것이다.
서로 관계가 있는 데이터가 여러 테이블로 나뉘어 저장되므로 각 테이블에 저장된 데이터를 효과적으로 검색하기 위해 필요하다.

JPQL, Querydsl은 조인연산을 제공하여 복잡한 쿼리 작성을 수행할 수 있다.

기본 조인

조인의 기본 문법은 첫 번째 파라미터에 조인 대상을 지정하고, 두 번째 파라미터에 alias로 사용할 QType을 지정하면 된다

List<Member> result = queryFactory
 .selectFrom(member)
 .join(member.team, team)
 .where(team.name.eq("teamA"))
 .fetch();

팀 A에 소속된 모든 회원을 출력하는 쿼리이다.
실제로 작동되는 쿼리는 다음과 같다.

 select
            member0_.user_id as user_id1_0_,
            member0_.age as age2_0_,
            member0_.team_id as team_id4_0_,
            member0_.username as username3_0_ 
        from
            member member0_ 
        left outer join
            team team1_ 
                on member0_.team_id=team1_.team_id 
        where
            team1_.name=?     

SQL에서 사용하는 innerjoin, left outer join, right outer join 모두 사용이 가능하다.

세타 조인

세타 조인은 연관관계가 없는 필드로 조인하는 것을 말한다.

List<Member> result = queryFactory
 .select(member)
 .from(member, team)
 .where(member.username.eq(team.name))
 .fetch();

회원의 이름과 팀 이름은 연관관계가 없지만 두 필드의 값이 같은 회원을 조회한다면 세타 조인을 통해 쿼리를 작성할 수 있다.
실제로 작동되는 쿼리는 다음과 같다.

select
            member0_.user_id as user_id1_0_,
            member0_.age as age2_0_,
            member0_.team_id as team_id4_0_,
            member0_.username as username3_0_ 
        from
            member member0_ cross 
        join
            team team1_ 
        where
            member0_.username=team1_.name

cross join이란 집합에서 나올 수 있는 모든 경우의 수이기 때문에 where 절을 통해 필터링하는 것을 알 수 있다.

ON 절

조인 대상 필터링

List<Tuple> result = queryFactory
 .select(member, team)
 .from(member)
 .leftJoin(member.team, team).on(team.name.eq("teamA"))
 .fetch();

회원을 모두 조회하지만 팀 이름이 'teamA'인 경우 Team 조회를 수행한다.
팀 이름이 'teamA'인 경우 Team 정보를 같이 조회하지만 아닌 경우 null 값이 들어간다.

select
            member0_.user_id as user_id1_0_0_,
            team1_.team_id as team_id1_1_1_,
            member0_.age as age2_0_0_,
            member0_.team_id as team_id4_0_0_,
            member0_.username as username3_0_0_,
            team1_.name as name2_1_1_
        from
            member member0_
        left outer join
            team team1_
                on member0_.team_id=team1_.team_id
                and (team1_.name=?)
         

연관관계 없는 엔티티 외부 조인

List<Tuple> result = queryFactory
 .select(member, team)
 .from(member)
 .leftJoin(team).on(member.username.eq(team.name))
 .fetch();

연관관계가 없는 엔티티 외부 조인은 left join id 값으로 매칭을 해주는 기존 연관관계와 다르게 순수 on 절의 조건으로 매칭을 시킨다.
일반 조인 : leftjoin(member.team, team)
on 조인 : join(team).on(member.username.eq(team.name))

Fetch 조인

fetch join은 sql 조인을 활용하여 연관된 엔티티를 sql 한번에 조회하는 기능으로 성능 최적화에 사용된다.

Member result = queryFactory
                .selectFrom(member)
                .join(member.team, team).fetchJoin()
                .where(member.username.eq("member1"))
                .fetchOne();

엔티티 설계를 할 때 N+1문제로 인해 LAZY 설정을 수행했지만 fetch join을 통해 연관된 엔티티까지 한 번에 조회가 가능하다.

select
        member0_.user_id as user_id1_0_0_,
                team1_.team_id as team_id1_1_1_,
        member0_.age as age2_0_0_,
                member0_.team_id as team_id4_0_0_,
        member0_.username as username3_0_0_,
                team1_.name as name2_1_1_
        from
        member member0_
        inner join
        team team1_
        on member0_.team_id=team1_.team_id
        where
        member0_.username=?

0개의 댓글

관련 채용 정보