1. 개요
1) JPA가 지원하는 다양한 쿼리 방법
- JPQL
- JPA Criteria
- QueryDSL
- Native SQL
- JDBC API
2) JPQL 소개
- JPA를 사용하면 Entity 객체를 중심으로 개발하지만 SQL은 DB의 테이블을 대상으로 쿼리를 수행
- 이러한 간극을 보완하기 위해 JPQL은 테이블이 아닌 Entity 객체를 대상으로 쿼리를 수행
- 즉, JPA는 SQL을 추상화한 JPQL이라는 객체 지향 쿼리 언어를 제공함; 특정 DB SQL에 의존하지 않음
- 이는 SQL문법과 유사하여 SELECT, FROM, WHERE, GROUP BY, HAVING, JOIN 지원
- JPQL = 객체지향 SQL ; JPQL은 결국 SQL로 변환됨
2. 기본 문법과 기능
1) JPQL 문법
SQL 문법과 대부분 비슷함
select_문 :: =
select_절
from_절
[where_절]
[groupby_절]
[having_절]
[orderby_절]
update_문 :: = update_절 [where_절]
delete_문 :: = delete_절 [where_절]
- 엔티티는 대문자로 시작, 속성은 소문자로 시작(Member, age)
- JPQL 키워드는 대소문자 구분 X(SELECT, FROM 등)
- 쿼리에 엔티티 이름 사용(테이블 이름이 아닌)
- 별칭 필수(as는 생략 가능)
2) TypeQuery와 Query
- TypeQuery: 반환 타입이 명확할 때 사용
TypedQuery<Member> query =
em.createQuery("SELECT m FROM Member m", Member.class);
- Query: 반환 타입이 명확하지 않을 때 사용
Query query =
em.createQuery("SELECT m.username, m.age from Member m");
3) 결과 조회 API
- query.getResultList()
- 결과가 하나 이상일 때, 리스트 반환
- 결과가 없으면 빈 리스트 반환
- query.getSingleResult()
- 결과가 정확히 하나일 때 사용, 단일 객체 반환
- 결과가 없으면: javax.persistence.NoResultException
- 둘 이상이면: javax.persistence.NonUniqueResultException
4) Parameter Binding
- 이름 기준
SELECT m FROM Member m where m.username=:username
query.setParameter("username", usernameParam);
- 위치 기준(유지보수 측면에서 불리하므로 비추)
SELECT m FROM Member m where m.username=?1
query.setParameter(1, usernameParam);
5) Projection
- SELECT 절에 조회할 대상을 지정하는 것
- 프로젝션 대상: 엔티티, 임베디드 타입, 스칼라 타입(숫자, 문자 등 기본 데이터 타입)
- SELECT m FROM Member m -> 엔티티 프로젝션
- SELECT m.team FROM Member m -> 엔티티 프로젝션
- SELECT m.address FROM Member m -> 임베디드 타입 프로젝션
- SELECT m.username, m.age FROM Member m -> 스칼라 타입 프로젝션
- 여러 값 조회 방법
- Query 타입으로 조회
- Object[] 타입으로 조회
- new 명령어로 조회
- 결과값의 형식에 맞는 DTO를 만들고 그 DTO 객체로 결과를 받음
- 패키지 명을 포함한 전체 클래스 명 입력
- 순서와 타입이 일치하는 생성자 필요
SELECT new jpabook.jpql.UserDTO(m.username, m.age) FROM Member m
6) Paging
- setFirstResult(int startPosition) : 조회 시작 위치(0부터)
- setMaxResults(int maxResult) : 조회할 데이터 수
String jpql = "select m from Member m orderby m.name desc";
List<Member> resultList = em.createQuery(jpql, Member.class)
.setFirstResult(10) // 인덱스 10부터
.setMaxResults(20) // 20개 가져와
.getResultList();
7) Join
- Inner Join : 기준 테이블과 조인 테이블 모두 데이터가 존재해야 조회됨
- Outer Join: 기준 테이블에만 데이터가 존재하면 조회됨
- Theta Join: 두 테이블 간의 속성 값을 비교(=,≠,≥,≤,>,<)하여 조건을 만족하는 데이터만 조회
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 // 세타 조인
- ON 절
- 조인 대상 필터링 : Ex) 회원과 팀을 조인하면서, 팀 이름이 A인 팀만 조인
- 연관관계 없는 엔티티 외부 조인 : Ex) 회원의 이름과 팀의 이름이 같은 대상 외부 조인
'JPA' 카테고리의 다른 글
[JPA] JPA의 Entity에 기본 생성자가 필수인 이유 (0) | 2023.12.17 |
---|---|
[JPA] N+1 문제 및 해결방안 (0) | 2022.10.11 |