[QueryDSL] JOIN + JOIN FETCH

KMS·2022년 5월 9일
0

QueryDSL

목록 보기
5/8

QueryDSL에서 JOIN을 하는 방식과, 각 JOIN을 했을때의 차이점들을 보도록 하겠습니다.

Inner Join

	@Test
    void join1() {
        factory = new JPAQueryFactory(em);
        QTeam team = QTeam.team;
        QMember member = QMember.member;

        /**
         * select member0_.member_id as member_i1_0_, member0_.created_date as created_2_0_, member0_.last_modified_date as last_mod3_0_, member0_.age as age4_0_, member0_.team_id as team_id6_0_, member0_.username as username5_0_
         * from member member0_
         * inner join team team1_
         * on member0_.team_id=team1_.team_id
         * where team1_.name='TeamA';
         */
        List<Member> members = factory.selectFrom(member)
                .join(member.team, team) // join() == innerJoin(); leftJoin, rightJoin()도 가능
                .where(team.name.eq("TeamA"))
                .fetch();

        Assertions.assertThat(members)
                .extracting("username")
                .containsExactly("MemberA", "MemberB", "MemberC");
    }

처리되는 쿼리문:

select member0_.member_id as member_i1_0_, member0_.created_date as created_2_0_, member0_.last_modified_date as last_mod3_0_, member0_.age as age4_0_, member0_.team_id as team_id6_0_, member0_.username as username5_0_
from member member0_
inner join team team1_
on member0_.team_id=team1_.team_id
where team1_.name='TeamA';

Outer Join

	@Test
    void join2() {
        factory = new JPAQueryFactory(em);
        QTeam team = QTeam.team;
        QMember member = QMember.member;

        List<Tuple> resultLeftJoin = factory
                .select(member, team)
                .from(member)
                .leftJoin(member.team, team)
                .on(team.name.eq("TeamA"))
                .fetch();

        Assertions.assertThat(resultLeftJoin.size()).isEqualTo(4);
    }

처리되는 쿼리문:

select member0_.member_id as member_i1_0_0_, team1_.team_id as team_id1_1_1_, member0_.created_date as created_2_0_0_, member0_.last_modified_date as last_mod3_0_0_, member0_.age as age4_0_0_, member0_.team_id as team_id6_0_0_, member0_.username as username5_0_0_, team1_.created_date as created_2_1_1_, team1_.last_modified_date as last_mod3_1_1_, team1_.name as name4_1_1_
from member member0_
left outer join team team1_
on member0_.team_id=team1_.team_id and (team1_.name='TeamA');

Inner Join vs. Outer Join

Inner Join:

(SELECT m., t. FROM member m JOIN team t ON m.team_id=t.id AND t.name = 'TeamA';)
tuple = [Member(id=3, username=MemberA, age=25), Team(id=1, name=TeamA)]
tuple = [Member(id=4, username=MemberB, age=35), Team(id=1, name=TeamA)]
tuple = [Member(id=5, username=MemberC, age=45), Team(id=1, name=TeamA)]

Outer Join:

(SELECT m., t. FROM member m LEFT JOIN team t ON m.team_id=t.id AND t.name = 'TeamA';)
tuple = [Member(id=3, username=MemberA, age=25), Team(id=1, name=TeamA)]
tuple = [Member(id=4, username=MemberB, age=35), Team(id=1, name=TeamA)]
tuple = [Member(id=5, username=MemberC, age=45), Team(id=1, name=TeamA)]
tuple = [Member(id=6, username=MemberD, age=55), null]

Inner Join의 경우 조인하는 테이블(Team)이 조건에 맞는 경우들의 값들만 반환하며, Outer Join의 경우 조인 당하는 테이블(Member)의 모든 값들을 반환하는데, 조건이 맞을 경우 Team의 값들도 같이 보여주며, 조건에 맞지 않을경우 null을 반환합니다.
해당 내용은 SQL에서의 JOIN과 관련된 내용이므로, 더 자세한 설명은 SQL의 JOIN을 학습하시면 됩니다.

JOIN FETCH

	@Test
    void fetchJoinYes() {
        factory = new JPAQueryFactory(em);
        QMember member = QMember.member;
        QTeam team = QTeam.team;

        em.flush();
        em.clear();

        Member findMember = factory
                .selectFrom(member)
                .join(member.team, team).fetchJoin()
                .fetchFirst();

        boolean isLoaded = emf.getPersistenceUnitUtil().isLoaded(findMember.getTeam()); //로딩이 된 엔티티인지 아닌지 알려줌
        Assertions.assertThat(isLoaded).isTrue();
    }

QueryDSL에서 JOIN FETCH를 하고 싶은 경우, fetchJoin()을 추가하면 됩니다. JOIN FETCH에 관한 내용은 https://velog.io/@k_ms1998/JPA-JPQL-%EC%A1%B0%EC%9D%B8JOIN 을 참고하시면 됩니다.

profile
Student at Sejong University Department of Software

0개의 댓글