오봉이와 함께하는 개발 블로그

JPA - 조인, 서브 쿼리 본문

BE/JPA

JPA - 조인, 서브 쿼리

오봉봉이 2022. 6. 30. 02:05
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: 같은 의미, 조건을 하나라도 만족하면 참
  • [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