JPA - jpql join

Seongjin Jo·2022년 12월 28일
0

JPA

목록 보기
1/3

✔ JPA 쿼리 방법


jpa는 다양한 쿼리 방법을 지원한다. jpql,jpa criteria,querydsl,native sql, jdbc api직접사용,mybatis 등등 많다

✔ JPQL


JPA를 사용하면 엔티티 객체를 중심으로 개발할 수 있다. 문제는 검색 쿼리. 검색을 할 때도 테이블이 아닌 엔티티 객체를 대상으로 검색.

jpql과 실행된 sql 이다.
18살 이상의 회원을 조회하는 쿼리.

✔ JPQL JOIN

1.조인

내부 조인: SELECT m FROM Member m [INNER] JOIN m.team t
외부 조인: SELECT m FROM Member m LEFT [OUTER] JOIN m.team t 
세타 조인: select count(m) from Member m, Team t where m.username = t.name

2.ON절
1.조인 대상 필터링
예) 회원과 팀을 조인하면서, 팀 이름이 A인 팀만 조인

JPQL: SELECT m, t FROM Member m LEFT JOIN m.team t on t.name = 'A' 
SQL:
SELECT m.*, t.* 
FROM Member m LEFT JOIN Team t 
ON m.TEAM_ID=t.id and t.name='A' 

2.연관관계 없는 엔티티 외부 조인
예) 회원의 이름과 팀의 이름이 같은 대상 외부 조인

JPQL: SELECT m, t FROM Member m LEFT JOIN Team t on m.username = t.name
SQL:
SELECT m.*, t.* 
FROM  Member m LEFT JOIN Team t 
ON m.username = t.name

✔ 서브 쿼리

나이가 평균보다 많은 회원
select m from Member m where m.age > (select avg(m2.age) from Member m2) 
한 건이라도 주문한 고객
select m from Member m where (select count(o) from Order o where m = o.member) > 0 
팀A 소속인 회원
select m from Member m where exists (select t from m.team t where t.name = ‘팀A') 
전체 상품 각각의 재고보다 주문량이 많은 주문들
select o from Order o where o.orderAmount > ALL (select p.stockAmount from Product p) 
어떤 팀이든 팀에 소속된 회원
select m from Member m where m.team = ANY (select t from Team t)

서브쿼리의 한계 : FROM 절의 서브 쿼리는 현재 JPQL에서 불가능, 조인으로 풀 수 있으면 풀어서 해결

✔ fetch join


JPQL에서 성능 최적화를 위해 제공하는 기능이다.
연관된 엔티티나 컬렉션을 SQL 한 번에 함께 조회 하는 기능.
join fetch 명령어 사용
페치 조인 ::= [ LEFT [OUTER] | INNER ] JOIN FETCH 조인경로

엔티티 패치 조인

• 회원을 조회하면서 연관된 팀도 함께 조회(SQL 한 번에) 
• SQL을 보면 회원 뿐만 아니라 팀(T.*)도 함께 SELECT
• [JPQL] : select m from Member m join fetch m.team 
• [SQL] : SELECT M.*, T.* 
		  FROM MEMBER M INNER JOIN TEAM T 
          ON M.TEAM_ID=T.ID 

member와 team이 다대일 일대다 연관관계라고 가정해보자. 원래 jpa 일대다 다대일 등 연관관계에서는 지연로딩(LAZY) 방식이다.또한 일반 조인 실행시 연관된 엔티티를 함께 조회하지 않는다. 그렇기 때문에 member를 조회하는 쿼리를 날리면 team의 proxy객체가 호출되어서 team의 프로퍼티를 조회하게 되면 쿼리가 한번 더 나가게 되서 흔히 말하는 N+1 문제가 발생한다. 그렇기 때문에 fetch join을 이용하게되면 member와 team의 엔티티객체에 한번에 select 쿼리를 날려member.getTeamName() 이런식의 코드를 짜도 프록시 객체가 아닌 진짜 객체가 조회된다. 쿼리 한 번에 다 해결할 수 있다.

패치조인 일반조인 차이점
1.페치 조인을 사용할 때만 연관된 엔티티도 함께 조회(즉시 로딩)
2.페치 조인은 객체 그래프를 SQL 한번에 조회하는 개념

✔ 패치 조인과 DISTINCT


SQL의 DISTINCT는 중복된 결과를 제거하는 명령이다.
아래 방식 처럼 사용한다.

select distinct t
from Team t join fetch t.members
where t.name = ‘팀A’ 

0개의 댓글