[JPA] 컬렉션 페치 조인

컬렉션 페치 조인

  • 일대다 관계인 컬렉션을 함께 조회시 사용한다.
  • 연관된 엔티티들을 한번의 쿼리로 가져올 수 있음
  • 예시
    SELECT t FROM Team t JOIN FETCH t.members WHERE t.name = '팀A'
  • 실행된 SQL
    SELECT T.*, M.* FROM TEAM T INNER JOIN MEMBER M ON T.ID = M.TEAM_ID WHERE T.NAME = '팀A'
    • TEAM 테이블과 MEMEBER 테이블을 내부 조인하여 팀A 에 소속된 모든 회원을 조회함
    @BeforeEach
        void setUp() {
            List<Team> teams = new ArrayList<>();
            Team team = new Team();
            team.setName("팀1");
            em.persist(team);
            // 팀만들어주기
            
            // 멤버 50개 만들어주기
            for (int i = 0; i < 50; i++) {
                Member member = new Member();
                member.setName("ipeac" + i);
                member.setAge(i);
                
                if (i % 2 == 0) {
                    member.setTeam(team);
                }
                
                em.persist(member);
            }
        }
        
        @Test
        void testCollectionFetchJoin() {
            List<Team> teams = em.createQuery(
                                     "select t from Team t join fetch t.members where t.name= :teamName", Team.class
                                 )
                                 .setParameter("teamName", "팀1")
                                 .getResultList();
            for (Team team : teams) {
                System.out.println("team = " + team);
                
                for (Member member : team.getMembers()) {
                    System.out.println("member.getName() = " + member.getName());
                }
            }
        }
    team = Team(id=1, name=팀1, members=[Member(id=1, name=ipeac0, age=0, address=null, favoriteFoods=[], addressHistory=[]), Member(id=3, name=ipeac2, age=2, address=null, favoriteFoods=[], addressHistory=[]), Member(id=5, name=ipeac4, age=4, address=null, favoriteFoods=[], addressHistory=[]), Member(id=7, name=ipeac6, age=6, address=null, favoriteFoods=[], addressHistory=[]), Member(id=9, name=ipeac8, age=8, address=null, favoriteFoods=[], addressHistory=[]), Member(id=11, name=ipeac10, age=10, addr...........
    member.getName() = ipeac0
    member.getName() = ipeac2
    member.getName() = ipeac4
    member.getName() = ipeac6
    member.getName() = ipeac8
    member.getName() = ipeac10
    member.getName() = ipeac12
    member.getName() = ipeac14
    member.getName() = ipeac16
    member.getName() = ipeac18
    member.getName() = ipeac20
    member.getName() = ipeac22
    member.getName() = ipeac24
    member.getName() = ipeac26
    member.getName() = ipeac28
    member.getName() = ipeac30
    member.getName() = ipeac32
    member.getName() = ipeac34
    member.getName() = ipeac36
    member.getName() = ipeac38
    member.getName() = ipeac40
    member.getName() = ipeac42
    member.getName() = ipeac44
    member.getName() = ipeac46
    member.getName() = ipeac48

    주의

    1. 중복
      1. 컬렉션 페치 조인은 SQL 수준에서 연관된 엔티티수 만큼 부모 엔티티가 중복될 수 있음.
      1. JPA 는 알아서 처리를 해주긴해.. 근데 큰 결과 집합에서는 성능상의 고려가 필요하다.
    1. 페이징
      1. 컬렉션 페치 조인 사용시 페이징 API
        1. setFirstResult, setMaxResults
        1. 함께 사용하는 것은 권장 X
        1. 메모리에서 페이징처리를 하게 됨으로 많은 양의 데이터와 함께 사용할 경우 메모리를 많이 소비함.
    1. 카테시안 곱 문제를 발생시킬 수 있습니다.
      1. 두 테이블 AB 가 존재할 때
      1. 각각 n 과 m 행을 가지고 있는 경우
      1. 조인을 수행하는 경우
      1. n * m 결과의 행을 수행한다.
        1. 이는 예상치 않은 성능 저하를 초래할 수 있습니다.
        1. 특별히 주의가 필요하다.

      근데 이 문제는 단순한 페치 조인만의 문제는 아니긴하다.

      SQL 레벨에서 고려해야할 문제이기도 하다.


Uploaded by N2T

'자바 > JPA' 카테고리의 다른 글

[JPA] JPQL 조인  (0) 2023.11.09
[JPA] 페치 조인  (0) 2023.11.09
[JPA] 페치 조인과 일반 조인의 차이점  (0) 2023.11.09
[JPA] __**@AttributeOverride: 속성 재정의**__  (0) 2023.11.09
[JPA] 값 타입- 기본값 타입  (0) 2023.11.06