Notice
Recent Posts
Recent Comments
Link
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

개발자되기 프로젝트

Join 본문

인프런/[인프런] QueryDsl

Join

Seung__ 2021. 9. 2. 23:09

1. 기본 조인


  • 조인의 기본 문법은 첫 번째 파라미터에 조인 대상을 지정하고,
  • 두 번째 파라미터에 별칭(alias)을 사용하여  Q타입을 지정.(QTeam.team)
@Override
    public <P> Q join(EntityPath<P> target, Path<P> alias) {
        return queryMixin.join(target, alias);
    }
 /**
     * 팀A에 소속된 모든 회원 조회
     */
    @Test
    public void join(){
        List<Member> result = queryFactory
                .selectFrom(member)
                .join(member.team, QTeam.team)
                .where(team.name.eq("teamA"))
                .fetch();

        assertThat(result)
                .extracting("username")
                .containsExactly("member1", "member2");
    }
select
        member1 
    from
        Member member1   
    inner join
        member1.team as team 
    where
        team.name = ?1 */ select
            member0_.member_id as member_i1_1_,
            member0_.age as age2_1_,
            member0_.team_id as team_id4_1_,
            member0_.username as username3_1_ 
        from
            member member0_ 
        inner join
            team team1_ 
                on member0_.team_id=team1_.team_id 
        where
            team1_.name=?

 

2. 세타조인


  • 연관관계가 없는 둘을 조인시킴
  • from 절에 여러 엔티티를 선택해서 세타 조인
  • 외부 조인 불가능 다음에 설명할 조인 on을 사용하면 외부 조인 가능
 /**
     * 세타조인
     * 회원의 이름이 팀 이름과 같은 회원을 조회
     */
    @Test
    public void theta_join(){
        em.persist(new Member("teamA"));
        em.persist(new Member("teamB"));

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

 

3. 조인 on 절


  • 조인 대상 필터링
  • 연관관계 없는 엔티티 외부 조인

 

 

3.1 조인 대상 필터링

  • 회원과 팀을 조인하면서, 팀 이름이 teamA인 팀만 조인, 회원은 모두 조회\
  • select m, t from Member m left join m.team t on t.name = 'teamA'
  • left join이기 때문에 member는 다 가져오고 teamA가 아닌 경우는 null
/**
     * 회원과 팀을 조인하면서, 팀 이름이 teamA인 팀만 조인, 회원은 모두 조회
     * select m, t from Member m left join m.team t on t.name = 'teamA'
     */
    @Test
    public void join_on_filtering(){

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

        for (Tuple tuple : result) {
            System.out.println("tuple = " + tuple);

        }
    }
    /* select
        member1,
        team 
    from
        Member member1   
    left join
        member1.team as team with team.name = ?1 */ select
            member0_.member_id as member_i1_1_0_,
            team1_.team_id as team_id1_2_1_,
            member0_.age as age2_1_0_,
            member0_.team_id as team_id4_1_0_,
            member0_.username as username3_1_0_,
            team1_.name as name2_2_1_ 
        from
            member member0_ 
        left outer join
            team team1_ 
                on member0_.team_id=team1_.team_id 
                and (
                    team1_.name=?
                )
tuple = [Member(id=3, username=member1, age=10), Team(id=1, name=teamA)]
tuple = [Member(id=4, username=member2, age=20), Team(id=1, name=teamA)]
tuple = [Member(id=5, username=member3, age=30), null]
tuple = [Member(id=6, username=member4, age=40), null]
  • on 절을 활용해 조인 대상을 필터링 할 때, 외부조인이 아니라 내부조인(inner join)을 사용하면,
  • where 절에서 필터링 하는 것과 기능이 동일하다. 따라서 on 절을 활용한 조인 대상 필터링을 사용할 때,
  • 내부조인 이면 익숙한 where 절로 해결하고, 정말 외부조인이 필요한 경우에만 이 기능을 사용하자.
  • left join인 경우 값이 없어도 가져와야 할 경우가 있기 때문에 on절이 의미가 있음.

 

 

 

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

  • from에 바로 team을 넣음.-> id로 찾는게 아님 
  • 아래 예제는 연관관계가 아니어도 이름이 같은 경우에 조인함.--> 조건이 맞지 않으면 null
    /**
     * 연관관계 없는 엔티티 외부 조인
     * 회원의 이름이 팀 이름과 같은 회원을 조회
     */
    @Test
    public void join_on_no_relation(){
        em.persist(new Member("teamA"));
        em.persist(new Member("teamB"));

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

        for (Tuple tuple : result) {
            System.out.println("tuple = " + tuple);

        }
    }
    /* select
        member1,
        team 
    from
        Member member1   
    left join
        Team team with member1.username = team.name */ select
            member0_.member_id as member_i1_1_0_,
            team1_.team_id as team_id1_2_1_,
            member0_.age as age2_1_0_,
            member0_.team_id as team_id4_1_0_,
            member0_.username as username3_1_0_,
            team1_.name as name2_2_1_ 
        from
            member member0_ 
        left outer join
            team team1_ 
                on (
                    member0_.username=team1_.name
                )
tuple = [Member(id=3, username=member1, age=10), null]
tuple = [Member(id=4, username=member2, age=20), null]
tuple = [Member(id=5, username=member3, age=30), null]
tuple = [Member(id=6, username=member4, age=40), null]
tuple = [Member(id=7, username=teamA, age=0), Team(id=1, name=teamA)]
tuple = [Member(id=8, username=teamB, age=0), Team(id=2, name=teamB)]
  • 하이버네이트 5.1부터 on 을 사용해서 서로 관계가 없는 필드로 외부 조인하는 기능이 추가되었다. 
  •  leftJoin() 부분에 일반 조인과 다르게 엔티티 하나만 들어감.
    • 일반조인: leftJoin(member.team, team)
    • on조인: from(member).leftJoin(team).on(xxx)

 

 

4. 페치조인


  • join(), leftJoin() 등 조인 기능 뒤에 fetchJoin() 이라고 추가하면 된다.
    @PersistenceUnit
    EntityManagerFactory emf;

	@Test
    public void fetchJoin(){
        em.flush();
        em.clear();

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

        //team이 이미 로딩된 엔티티 인지 확인
        boolean loaded = emf.getPersistenceUnitUtil().isLoaded(findMember.getTeam());
        assertThat(loaded).as("페치 조임 미적용").isTrue();
    }
    /* select
        member1 
    from
        Member member1   
    inner join
        fetch member1.team as team 
    where
        member1.username = ?1 */ select
            member0_.member_id as member_i1_1_0_,
            team1_.team_id as team_id1_2_1_,
            member0_.age as age2_1_0_,
            member0_.team_id as team_id4_1_0_,
            member0_.username as username3_1_0_,
            team1_.name as name2_2_1_ 
        from
            member member0_ 
        inner join
            team team1_ 
                on member0_.team_id=team1_.team_id 
        where
            member0_.username=?

 

5. GitHub : 210902 join


 

GitHub - bsh6463/Querydsl

Contribute to bsh6463/Querydsl development by creating an account on GitHub.

github.com

 

'인프런 > [인프런] QueryDsl' 카테고리의 다른 글

Case 문  (0) 2021.09.02
서브쿼리, SubQuery  (0) 2021.09.02
집합  (0) 2021.09.01
페이징  (0) 2021.09.01
정렬  (0) 2021.09.01
Comments