인프런 커뮤니티 질문&답변

안호성님의 프로필 이미지
안호성

작성한 질문수

실전! Querydsl

조인 - on절

on join 을 사용할 경우 select 에 하나의 객체만 넣으면 안되나요?

작성

·

324

0

@Test
    public void join_on() {
        List<Tuple> result = query
                .select(member, team)
                .from(member)
                .leftJoin(member.team, team)
                .on(team.name.eq("teamA"))
                .fetch();

        for (Tuple tuple : result) {
            System.out.println(tuple);
        }

    }

이게 강사님께서 설명해주신 코드입니다. 이렇게 조회하게 되면 정상적으로 tuple 에 team name 이 "teamA" 것만 포함됩니다.

근데 여기서 select 에 member 만 추가하게 되면 다음과 같습니다.

@Test
    public void select_one() {
        List<Member> result = query
                .selectFrom(member)
                .leftJoin(member.team, team)
                .on(team.name.eq("teamA"))
                .fetch();

        for (Member member1 : result) {
            System.out.println(member1);
            System.out.println(member1.getTeam());
        }
    }

이럴 경우 member getTeam 을 통해 team 을 확인하면 "teamB" 인 team도 포함되어 있습니다.

왜 이렇게 되는지 궁금해서 sql 을 봤는데 순서대로 아래가 강사님이 짜주신 select(member, team) 으로 발생한 sql 이고

select
        m1_0.member_id,
        m1_0.age,
        m1_0.team_id,
        m1_0.username,
        t1_0.team_id,
        t1_0.name 
    from
        member m1_0 
    left join
        team t1_0 
            on t1_0.team_id=m1_0.team_id 
            and t1_0.name=?

 

아래가 제가 임의로 짠 select(member) 만 해서 발생한 sql입니다.

select
        m1_0.member_id,
        m1_0.age,
        m1_0.team_id,
        m1_0.username 
    from
        member m1_0 
    left join
        team t1_0 
            on t1_0.team_id=m1_0.team_id 
            and t1_0.name=?

보면 select 하는 부분만 다르고 left join 하는 부분은 완벽하게 같은데.. 왜 위의 코드로 실행하면 정상적으로 teamA 만 join 되고 아래 코드로 실행하면 teamB까지 join 되는 건가요..?

답변 2

0

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. 안호성님

도움을 드리고 싶지만 질문 내용만으로는 답변을 드리기 어렵습니다.

실제 동작하는 전체 프로젝트를 압축해서 구글 드라이브로 공유해서 링크를 남겨주세요.

구글 드라이브 업로드 방법은 다음을 참고해주세요.

https://bit.ly/3fX6ygx

 

주의: 업로드시 링크에 있는 권한 문제 꼭 확인해주세요

 

추가로 다음 내용도 코멘트 부탁드립니다.

1. 문제 영역을 실행할 수 있는 방법

2. 문제가 어떻게 나타나는지에 대한 상세한 설명

감사합니다.

0

안녕하세요, 인프런 AI 인턴이에요.
조회하신 코드에 대해 설명해드리겠습니다.

첫 번째 코드에서는 tuple로 member와 team을 함께 조회하고, 조인 조건으로 team의 name이 “teamA”인 것만 선택하여 가져왔습니다. 따라서 결과로 반환되는 tuple에는 team name이 “teamA”인 것만 포함됩니다.

두 번째 코드에서는 member만 조회하고, 조인 조건으로 team의 name이 “teamA”인 것만 선택하여 가져왔습니다. 이때 결과로 반환되는 member에는 선택된 member만 포함되지만, member의 getTeam()을 통해 team을 확인하면 team name이 “teamA”인 것 뿐만 아니라 다른 team도 포함되어 있습니다.

이렇게 동작하는 이유는 JPA에서의 조인 방식과 관련이 있습니다. JPA는 기본적으로 레이지 로딩을 적용하여 연관된 객체를 필요한 시점에 가져오게 됩니다. 따라서 두 번째 코드에서는 member만 조회하며, team은 필요할 때 getTeam()을 통해 추가로 가져옵니다. 따라서 모든 member에 대해 team을 한 번에 가져오는 것이 아니라, 필요한 시점에 team을 가져오는 것입니다.

이를 해결하기 위해서는 member와 team의 연관 관계를 Eager로 설정하거나, 쿼리를 수정하여 모든 member에 대한 team을 함께 가져와야 합니다. 예를 들어, 다음과 같이 쿼리를 수정할 수 있습니다.

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

fetchJoin()을 사용하여 team을 함께 가져오도록 설정하면, 모든 member에 대한 team을 함께 조회할 수 있습니다.

추가적으로, JPA의 연관 관계 설정에 대해 더 자세히 알고 싶으시다면, 인프런에서 제공하는 관련 강의를 참고해보시는 것도 좋을 것 같아요.

더 궁금하신 점이 있다면 언제든지 물어보세요. 좋은 하루 되세요!

안호성님의 프로필 이미지
안호성

작성한 질문수

질문하기