JPQL
JPQL : Java Persistence Query Language
객체지향 쿼리 언어로, 테이블을 대상으로 쿼리하는 것이 아니라 엔티티 객체를 대상으로 쿼리한다.
SQL을 추상화해서 특정 데이터베이스 SQL에 의존하지 않는다.
JPQL은 결국 SQL로 변환된다.
기본 모델링
프로젝션
SELECT절에 조회할 대상을 지정할 수 있다. 프로젝션 대상으로 엔티티, 임베디드 타입, 스칼라 타입(숫자, 문자 등 기본 데이터)이 있다.
엔티티 프로젝션
select m from Member m
select m.team from Member m처음은 회원을 조회하고 두 번째는 회원과 연관된 팀을 조회한다. 이렇게 조회한 엔티티는 영속성 컨텍스트에서 관리된다.
두 번째는 다음처럼 변경할 수도 있다.
select t from Member m join m.team t실행되는 쿼리는 똑같다. 차이점이라고 한다면 개발자가 이 쿼리는 조인을 통해 데이터를 가져오는구나라고 인지하는 것 정도다.
임베디드 타입 프로젝션
select o.address from Order o임베디드 타입은 값 타입이기 때문에 조회의 시작점이 될 수 없다.
스칼라 타입 프로젝션
이렇게 두 개의 타입이 다른 필드를 프로젝션해서 타입을 지정할 수 없으므로 TypeQuery를 사용할 수 없다.
NEW명령어를 통하여 바로 DTO로 변환할 수 있다.
패키지 명을 포함한 전체 클래스명을 입력해야 한다.
순서와 타입이 일차하는 생성자가 필요하다.
페이징
JPA는 페이징을 다음 API로 추상화했다.
setFirstResult(int startPosition) : 조회 시작 위치(0부터 시작)
setMaxResult(int maxResult) : 조회할 데이터 수
조인
내부 조인
회원과 팀을 내부 조인해서 teamName에 소속된 회원을 찾는다. inner는 생략 가능하다.
외부 조인
outer는 생략 가능하다.
세타 조인
ON 절
회원과 팀을 조인할 때 팀의 이름이 "teamA"로 조인 대상을 필터링할 수 있다.
회원의 이름과 팀의 이름이 같은 대상을 외부 조인한다.
서브 쿼리
나이가 평균보다 많은 회원을 찾는다.
한 건이라도 주문한 고객을 찾는다.
서브 쿼리 지원 함수
[not] exists (subquery)
서브 쿼리에 결과가 존재하면 참이다. not은 반대
all, any, some (subquery)
비교 연산자와 같이 사용하며 all은 조건을 모두 만족해야 참이고 any나 some은 하나라도 만족하면 참이다.
[not] in (subquery)
서브쿼리의 결과 중 하나라도 같은 것이 있으면 참이다.
CASE 식
기본 CASE 식
COALESCE
사용자 이름이 없으면 '이름 없는 회원'을 반환한다.
NULLIF
사용자 이름이 '관리자'면 null을 반환하고 나머지는 이름을 그대로 반환한다.
Last updated