단일 값 연관 필드
-@ManyToOne , @OneToOne, 대상이 엔티티
-묵시적 내부조인 (inner join) 발생, 탐색 가능
-여기서 탐색이란 m.team.getName() 이런식으로 더 들어갈수 있다는 의미이다
컬렉션 값 연관 필드
-@OnetToMany, @ManyToMany, 대상이 컬렉션
-묵시적 내부 조인 발생, 탐색 불가능(객체중 어떤 객체가 나올지 모르니)
-FROM 절에서 명시적 조인을 통해 별칭을 얻으면 별칭을 통
해 탐색 가능
1.묵시적 조인: 경로 표현식에 의해 묵시적으로 SQL조인 발생.
Member -> Team 다대일 관계시 / select m.team from Member m
2. 명시적 조인: join 키워드 직접 사용
Member -> Team 다대일 관계시/select m from Member m join m.team t
★묵시적적 조인은 쿼리문만 봐서는 조인이 나가는지 알수가 없다. 또한 일어나는 상황을 한눈에 파악하기 어렵다. 그러므로 묵시적은 권장하지 않고 명시적 조인을 가능하면 사용하자!
SQL 조인 종류 x
JPQL 에서 성능 최적화를 위해 제공하는 기능
연관된 엔티티나 컬렉션을 SQL 한 번에 함께 조회
예시를 보면 이해가 쉽다. for문으로 돌릴때 처음 DB에 쿼리를 보내 값을 가져온뒤 프록시 객체에서 team 데이터를 건드리는 순간 또 쿼리가 나간다.
그동시에 1차캐쉬에 그데이터를 저장해 다음 Member2 는 1차캐시에서 값을 가져온다(쿼리문 x)
다음 팀B에대해서는 새롭게 DB에 쿼리를 날려 데이터를 가져온다
이렇게 2개의 데이터만 가져와도 쿼리문이 많이나가서 성능 저하를 유발한다. 이를 해결하기위해 Fetch Join을 써주자!!
회원 1을 DB에서 가져올때 1차캐시에 데이터를 넣고 회원 2를 가져올때 1차캐시에서 가져오므로 참조값은 같다.
Fetch join 을 사용해 연관된 멤버들값을 다 가져온다.
연관관계를 찾아간다라는 의미는 JPA 입장에서 데이터들이 다나온다는 가정하에 설계되있다. (데이터를 5개 가져왔는데 2개만 x)
다대일의 반대방향
페치조인이 ManyToOne 방향이라면 컬렉션 패치 조인은 일대다 방향이다
일대다 컬렉션 패치 조인은 데이터 뻥튀기가 일어난다 왜냐하면 팀의 입장에서는 맴버가 여러개 이기때문
SQL의 DISTINCT는 중복된 결과를 제거하는 명령
JPQL의 DISTINCT 2가지 기능 제공
• 1. SQL에 DISTINCT를 추가
• 2. 애플리케이션에서 엔티티 중복 제거
페치 조인을 사용할 때만 연관된 엔티티도 함께 조회(즉시 로딩)
페치 조인은 객체 그래프를 SQL 한번에 조회하는 개념
페치 조인 대상에는 별칭을 줄 수 없다.
둘 이상의 컬렉션은 페치 조인 할 수 없다.
컬렉션을 페치 조인하면 페이징 API(setFirstResult,
setMaxResults)를 사용할 수 없다.
ex) 데이터 2개+ 페이지 사이즈 1로 가져오면 데이터 하나만 인식된다.
->일대일, 다대일 같은 단일 값 연관 필드들은 페치 조인해도 페이징 가능
->하이버네이트는 경고 로그를 남기고 메모리에서 페이징(매우 위험)
엔티티에 직접 적용하는 글로벌 로딩 전략보다 우선함( ex: 지연로딩)
여러 테이블을 조인해서 엔티티가 가진 모양이 아닌 전혀 다른
결과를 내야 하면, 페치 조인 보다는 일반 조인을 사용하고 필요
한 데이터들만 조회해서 DTO로 반환하는 것이 효과적
필요없는 쿼리문 방지를 위해 지연로딩을 사용했다.
-> 연관된 테이블을 부를때 프록시부르고, 쿼리 날라가고... 낭비가 심히다!
->지연로딩으로 하되 fetch join 을 사용해 연관된 테이블이 필요할때만 한번에 불러오자!