본문 바로가기

웹 기술 쌈싸먹기/JPA

[JPA] 조인, 서브쿼리

조인

 

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절을 활용한 조인(JPA 2.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'

 

  • 연관관계 없는 엔티티 외부 조인(하이버네이트 5.1부터)
    • 예) 회원의 이름과 팀의 이름이 같은 대상 외부 조인
##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

 

 

서브 쿼리

 

1) JPA 서브쿼리 예제

  • 나이가 평균보다 많은 회원
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

 

2) 서브쿼리 지원함수

  • [NOT] EXISTS (subquery): 서브쿼리에 결과가 존재하면 참
    • {ALL | ANY | SOME} (subquery)
    • ALL 모두 만족하면 참
    • ANY, SOME: 같은 의미, 조건을 하나라도 만족하면 참
  • [NOT] IN (subquery): 서브쿼리의 결과 중 하나라도 같은 것이 있으면 참

 

3) 서브쿼리 지원함수 예제

  • 팀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)

 

4) JPA 서브 쿼리 한계

  • JPA는 WHERE, HAVING 절에서만 서브 쿼리 사용 가능
  • SELECT 절도 가능(하이버네이트에서 지원)
  • FROM 절의 서브 쿼리는 현재 JPQL에서 불가능
    • 조인으로 풀 수 있으면 풀어서 해결