본문 바로가기

JPA

2월 16일 JPA 일대다 관계, 컬렉션 페치 조인

(JPQL)

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'

 

문제점

1:다 조인이기 떄문에 데이터가 뻥튀기 된다 (join의 특성상 모든 경우의 수가 나와버리게 된다.)

즉 결과가 너무 많아져 버릴수 있다.

 

{team}

id     name

1      팀A

2      팀B

3      팀C

 

{member}

id     team_id     name

1      1                회원1

2      1                회원2

3      2                회원3

4      null             회원4

 

(pk > fk)

(team_id > member.team_id)

 

team join member

id     name     id     team_id     name

1      팀A        1      1                회원1

1      팀A        2      1                회원2

 

위 처럼 team에 입장에선 값이 1개가진

컬렉션의 입장에선 데이터가 2개인 상황이 된다.

JPA는 이런 늘어난 데이터를 모두 가져올 수 밖에 없다.

 

컬렉션 페치조인 중복제거

-SQL의 DISTINCT는 중복된 결과를 제거하는 명령

-JPQL의 DISTINCT는 2가지 기능을 제공

1.SQL에 DISTINCT를 추가

2.애플리케이션에서 엔티티 중복제거 

 DB가 아니라 JPA단에서 엔티티 중복제거

 

select distinct t

from team t join fetch t.members

where t.name = '팀A'

 

SQL에 DISTINCT는 모든 컬럼의 데이터가 일치해야 중복데이터로 인정한다.

즉 join으로 뻥튀기된 데이터는 일부만 같은데이터라서 같은데이터가 아니므로 중복제거에 실패한다.

 

이후 DISTINCT가 애플리케이션(JPA) 에서 중복제거를 시도한다.

JPA 에서 DISTINCT는 결과에서 기준이되는 from절에 PK값이 같으면 같은 데이터로 판단하여

하나만 남기고 삭제해 준다.

 

join 과 joinFetch의 차이점

-그냥 join은 from 에 대한 데이터만 퍼올린다.(최초)

-join fetch는 from과 join에 데이터를 모두 불러오게 된다.

-JPQL은 결과를 반환할때 연관관계를 고려하지 않는다.

-단지 select절에 지정한 엔티티만을 조회한다.

 

-여기서는 팀 엔티티만 조회하고 회원엔티티는 조회안한다.

-페치조인을 사용할 때만 연관된 엔티티를 함께 조회 (즉시로딩)

-페치조인은 객체그래프를 SQL 한번에 조회하는 개념이다.

 

대부분 n+1문제는 join fetch로 해결한다.

 

'JPA' 카테고리의 다른 글

2월 17일 JPA JPQL 다형성 쿼리  (0) 2023.02.17
2월 16일 JPA JPQL 페치조인의 특징과 한계  (0) 2023.02.16
2월 16일 JPA JPQL fetch Join  (0) 2023.02.16
2월 15일 JPA JPQL 경로 표현식  (0) 2023.02.15
2월 15일 JPA JPQL기본 함수  (0) 2023.02.15