스터디/스프링

스프링 공부 일지 - JPQL 패치 조인 with 간단한 예제

sleesm 2023. 3. 4. 20:34

이전 블로그 👉👉

2023.02.23 - [스터디/스프링] - 스프링 공부 일지 - 기본 키 매핑

 

스프링 공부 일지 - 기본 키 매핑

이전 블로그 👉👉 2023.02.16 - [스터디/스프링] - 스프링 공부 일지 - JPA 시작 스프링 공부 일지 - JPA 시작 이번에는 JPA 프로그래밍 기본편 강의를 들으면서 공부를 해보려고 한다!! 강의 링크 👉

sleecode.tistory.com

 

 

기록이 조금 뜸했는데

실전을 먼저 공부해서 그런지 중복되는 내용이 많아서

가볍지만 무겁지만 가볍게 듣느라 기록을 따로 하지 않았다

 

하지만 오늘 배운 JPOL은 조큼 필요할 것 같아서,,

 

 

아무튼

그 중 패치 조인에 대해서 예시와 함께 기록하고자 한다!!!!

 

 

 

 

 

 


 

 

일반 조인과 패치 조인

 

 

일반 조인

  • 연관된 엔티티를 같이 조회 시
    • 매번 지연로딩 발생
    • N + 1 문제

 

회원1, 팀A

- SQL로 지연 로딩 결과

 

회원2, 팀A

- 영속성 컨텍스트 (1차 캐시) 결과

 

회원3, 팀B

- SQL로 지연 로딩 결과

String query = "select m from Member m";

List<Member> result = em.createQuery(query, Member.class).getResultList();

for (Member member : result) {
    System.out.println("member.getUsername() = " + member.getUsername());
    System.out.println("member.getTeam().getName() = " + member.getTeam().getName());
}

 

 

 

 

 

1 : N 관계에서 패치 조인

  • 한 번에 쿼리로 전체를 받아올 수 있음 (즉시로딩과 비슷)
  • 엔티티에 직접 적용하는 글로벌 로딩 전략보다 높은 우선순위를 가짐
String query = "select m from Member m join fetch m.team";

List<Member> result = em.createQuery(query, Member.class).getResultList();

for (Member member : result) {
    System.out.println("member.getUsername() = " + member.getUsername());
    System.out.println("member.getTeam().getName() = " + member.getTeam().getName());
}

Fetch Join으로 한 번의 쿼리로 받아온 형태

 

 

 

N : 1 관계에서 패치 조인

  • team을 중심으로 members collection을 가져오는 것이기 때문에
  • 중복 결과 발생
String query = "select t from Team  t join fetch t.members";

List<Team> result = em.createQuery(query, Team.class).getResultList();

for (Team team : result) {
    System.out.println("member = " + team.getName());
    for(Member member : team.getMembers()){
        System.out.println("member.getUsername() = " + member.getUsername());
    }
}

 

중복된 값이 그대로 나온 결과

 

 

 

 

쿼리에 distinct를 추가

  • sql 결과에서 중복 제거
  • Entity 중복 제거
String query = "select distinct t from Team  t join fetch t.members";

List<Team> result = em.createQuery(query, Team.class).getResultList();

for (Team team : result) {
    System.out.println("member = " + team.getName());
    for(Member member : team.getMembers()){
        System.out.println("member.getUsername() = " + member.getUsername());
    }
}

엔티티 중복 제거된 결과

 

 

 

 

 

 

 

 


 

 

 

컬렉션 패치 조인에서 페이징을 하고 싶은 경우

 

 

- @BachSize 추가

  • 컬렉션 패치 조인에서 페이징을 하고 싶은 경우
  • 일반 조인으로 지연 로딩 사용
    • 지연 로딩을 size 크기만큼 한 번에 가져와서 처리해 줌
    • 1000 이하로 하는 것이 좋다!

 

 

 

- resources/META-INF/persistence.xml 에 다음 코드를 추가

  • @BachSize 와 같은 기능을 해줌
    • 범위가 글로벌 해지는 것!
  • 위 사진과 동일한 결과가 나옴
<property name="hibernate.default_batch_fetch_size" value="100"/>

 

 

 

 

 

 

 

 

 

 


조금 컴팩트하게 정보를 가져와봤다!!

 

이렇게 예제랑 실행결과를 같이 기록하면 확실히 알기 쉬울 것 같다 ^_^

 

아무튼 오늘의 공부도 끝!!!!!

이제 일타 스캔들 보러 가야겠다 😁😁😁

 

그럼 안녕!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌