오봉이와 함께하는 개발 블로그
JPA - 조인, 서브 쿼리 본문
728x90
조인
SQL 조인이랑 실행되는 것은 똑같지만, 엔티티를 중심으로 동작하기 때문에 객체 스타일로 문장을 작성해야 한다.
- 내부 조인
- 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
조인 간단한 예시
String query = "select m from Member m inner join m.team t"; // inner는 생략 가능.
String query = "select m from Member m left outer join m.team t"; // outer는 생략 가능.
String query = "select m from Member m, Team t where m.username = t.name";
List<Member> result = em.createQuery(query, Member.class)
.getResultList();
조인 - ON 절
- ON절을 활용한 조인
- 조인 대상 필터링
- 조인할 때 조인 대상을 미리 필터링한다.
- 연관관계 없는 엔티티 외부 조인
- 세타조인 할 때 처럼 아무 연관관계가 없는 조인을 할 수 있다.
- 예전에는 내부 조인만 가능했었음.
- 세타조인 할 때 처럼 아무 연관관계가 없는 조인을 할 수 있다.
- 조인 대상 필터링
조인 대상 필터링
예를 들어 회원과 팀을 조인하면서 팀 이름이 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'
연관관계 없는 엔티티 외부 조인
예를 들어 회원의 이름과 팀의 이름이 같은 대상 외부 조인
- 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
서브 쿼리
일반적인 SQL에서 말하는 서브 쿼리랑 같다.
- 나이가 평균보다 많은 회원
- 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
서브 쿼리 지원 함수
- [NOT] EXISTS (subquery): 서브쿼리에 결과가 존재하면 참
- {ALL | ANY | SOME} (subquery)
- ALL 모두 만족하면 참
- ANY, SOME: 같은 의미, 조건을 하나라도 만족하면 참
- {ALL | ANY | SOME} (subquery)
- [NOT] IN (subquery): 서브쿼리의 결과 중 하나라도 같은 것이 있으면 참
예제
- 팀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)
JPA 서브 쿼리의 한계
- JPA 표준 스펙에서는 WHERE, HAVING 절에서만 서브 쿼리를 사용 가능하다.
- 하이버네이트에서는 SELECT 절에서도 사용 가능하다.
- 예 : select (select avg(m1.age) from Member m1) as avgAge from Member m join Team t on m.username = t.name
- FROM 절의 서브 쿼리는 현재 JPQL에서는 불가능하다.
- 불가능하기 때문에 조인으로 풀 수 있으면 풀어서 해결하는 것이 좋다.
- 정 안되면 쿼리를 두 번에 나눠서 날려주거나, 네이티브 SQL을 사용해야 한다.
출처 : 인프런 김영한 지식공유자님의 스프링 부트와 JPA 실무 완전 정복 로드맵 강의
728x90
'BE > JPA' 카테고리의 다른 글
JPA - JPQL 함수 (0) | 2022.06.30 |
---|---|
JPA - JPQL 타입 표현과 기타식, 조건식 (0) | 2022.06.30 |
JPA - 페이징 (0) | 2022.06.30 |
JPA - 프로젝션(select) (0) | 2022.06.30 |
JPA - 기본 문법과 쿼리 API (0) | 2022.06.30 |
Comments