본 포스팅은 인프런 - 자바 ORM 표준 JPA 프로그래밍 (기본편) 을 강의를 바탕으로 공부하고 정리한 글입니다.
서브 쿼리
JPQL도 SQL처럼 서브 쿼리를 지원한다.
서브 쿼리는 쿼리 안에서 또 다른 쿼리를 말한다.
다음은 서브 쿼리를 사용한 예시이다.
/* 나이가 평균보다 많은 회원을 조회 */
select m from Member m
where m.age > (select avg(m2.age) from Memver m2)
예시를 보면 메인 쿼리와 서브 쿼리는 서로 전혀 관계가 없도록 한 것을 알 수 있다.
메인 쿼리에서는 m을 사용하지만, 서브 쿼리에서는 m2로 따로 정의해서 둘이 전혀 연관이 없도록 작성되어 있다.
이렇게 서브 쿼리를 짜야 성능이 잘 나온다.
/* 한 건이라도 주문한 고객을 조회 */
select m from Member m
where (select count(o) from Order o where m = o.member) > o
위 예제에서는 서브 쿼리에서 메인 쿼리에서 사용하는 m을 끌고와 사용하고 있다.
이렇다면 성능 문제가 있을 수 있다.
서브 쿼리 지원 함수
함수 | 설명 |
EXISTS | 서브 쿼리에 결과가 존재하면 참 |
ALL | 모두 만족하면 참 |
ANY, SOME | 조건을 하나라도 만족하면 참 |
IN | 서브 쿼리의 결과 중 하나라도 같은 것이 있으면 참 |
예제를 통해 서브 쿼리 지원 함수 사용법을 알아보자.
/* 팀A 소속인 회원 조회 */
select m form Member m
where EXISTS (select t from m.team t where t.name = 'A')
/* 전체 상품 각각의 재고보다 주문량이 많은 주문들 */
select o form 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의 서브 쿼리는 SQL의 서브 쿼리와 똑같지만 다음과 같은 한계점이 있다.
- JPA 표준 스펙에서는 WHERE, HAVING 절에서만 서브 쿼리 사용이 가능하다.
- JPA 구현체중 하이버네이트에서는 SELECT절에서도 서브 쿼리 사용을 지원한다.
→ 따라서 사용할 구현체의 스펙을 잘 알아보고 사용해야 한다. - FROM 절의 서브 쿼리는 현재 JPQL에서 불가능하다.
→ 조인으로 풀 수 있으면 조인으로 풀어서 해결한다.
/* select절에 서브 쿼리
* 하이버네이트에서만 사용 가능
*/
select (select avg(m1.age) from Member m1) as avgAge
from Member m
/* from절에 서브쿼리
* JPQL에서 불가능
*/
select mm.username, mm.age
from (select m.username, m.age from Member m) as mm
'🌱 Spring > JPA' 카테고리의 다른 글
[JPA] JPQL : 경로 표현식 (0) | 2023.07.04 |
---|---|
[JPA] JPA 설정 총 정리 : ddl-auto 옵션, 실행 쿼리 보기(SpringBoot 3.x 버전 변경 추가) (1) | 2023.04.19 |
[JPA] Auditing 기능을 사용해 공통 칼럼(등록일, 수정일 등) 관리하기 (0) | 2023.04.03 |
[JPA] OSIV (0) | 2022.12.27 |
[JPA] JPQL : 조인 (0) | 2022.11.04 |
[JPA] JPQL : 페이징 (0) | 2022.11.03 |
[JPA] JPQL : 기본 문법 (0) | 2022.10.29 |
[JPA] JPA가 지원하는 쿼리 방법 (JPQL, Criteria, QueryDsl) (0) | 2022.10.29 |