JPA (12) Join, Subquery, Case
26 Mar 2022김영한님의 자바 ORM 표준 JPA 프로그래밍 강의 정리
JOIN
-
SQL JOIN과 실행하는 것은 동일하지만 엔티티를 중심으로 동작
-
내부 조인
- inner 생략 가능
SELECT m FROM Member m [INNER] JOIN m.team t
-
외부 조인
- outer 생략 가능
SELECT m FROM Member m LEFT [OUTER] JOIN m.team t
-
세타 조인
- 연관 관계가 없을 때
SELECT count(m) FROM Member m, Team t where m.username = t.name
-
ON을 사용한 조인
-
JPA 2.1부터 지원
-
조인 대상 필터링
-- 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
-
Subquery
- 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 서브쿼리의 한계
- WHERE, HAVING 절에서만 서브 쿼리 사용 가능
- SELECT 절도 가능(하이버네이트에서 지원)
- FROM 절의 서브 쿼리(inline view) 불가
- 조인으로 해결할 수 있으면 조인 사용
JPQL 타입 표현
- 문자: ‘John’, ‘she’’s’
- 숫자: 10L(long), 10D(double), 10F(float)
- boolean: TRUE, FALSE
- enum: sample.enum.SampleEnum.SampleA (패키지 이름 포함)
- entity: TYPE(m) = member (상속 관계에서 사용)
- SQL과 문법이 같은 식
- EXIST, IN
- AND, OR, NOT
- =, >, >=, <, <=, <>
- BETWEEN, LIKE, IS NULL
CASE
- 기본 case 식
SELECT
CASE WHEN m.age <= 10 THEN '학생 요금'
WHEN m.age >= 60 THEN '경로 요금'
ELSE '일반 요금'
END
FROM Member m
- 단순 case 식
SELECT
CASE t.score
WHEN 'A' THEN '인센티브 120%'
WHEN 'B' THEN '인센티브 110%'
ELSE '인센티브 105%'
END
FROM Team t
COALESCE
: 하나씩 조회해서 null이 아니면 반환
SELECT COALESCE(m.username, '이름 없는 회원') FROM Member m
NULLIF
: 두 값이 같으면 null 반환, 다르면 첫번째 값 반환
SELECT NULLIF(m.username, '관리자') FROM Member m