1. 개요
- JPQL의 개념, 문법에 대해 알아보자.
2. 개념
- JPQL은 Java Persistence Query Language의 약자로 자바에서 사용하는 객체 지향 쿼리 언어이다. 객체 지향이라는 말에 맞게 쿼리를 작성할 때 테이블을 대상으로 작성하는게 아닌 엔티티를 대상으로 작성한다.
- JPQL은 결국에 SQL로 변환되며, 특정 데이터베이스에 의존하지 않는다.
3. JPQL 기본 문법
- JPQL은 SQL 문법과 거의 동일하지만 다른 점이 몇가지 있다.
1) 엔티티와 속성은 대소문자를 구분하므로 엔티티 클래스에 정의한 대로 사용해야 한다.
2) SELECT, FROM, WHERE 과 같은 JPQL 키워드는 대소문자를 구분하지 않는다.
3) SQL에서는 테이블 명을 입력했다면 JPQL에서는 테이블 명이 아닌 엔티티 명을 사용해야 한다.
4) 별칭이 필수이다. (ex. select m from Member m)
4. TypeQuery와 Query
- TypeQuery는 반환 값이 명확할 때, Query는 불명확할 때 사용한다.
// 반환 타입이 Member 클래스로 명확
TypedQuery<Member> typedQuery =
em.createQuery("select m from Member m", Member.class);
// 반환 타입이 username, id로 불명확
Query query =
em.createQuery("select m.username, m.id from Member m");
5. 결과 조회
- 결과 조회 시 Query 및 TypeQuery의 메서드인 getResultList(), getSingleResult() 중 하나를 사용한다.
5.1. getResultList
- 결과가 하나 이상일 때 리스트를 반환하고, 결과가 없을 때 빈 리스트를 반환한다.
- null 체크 할 필요가 없다.
5.2. getSingleResult
- 결과가 정확히 하나일 때 단일 객체를 반환하고, 없을 때 NoResultException, 둘 이상일 때 NonUniqueResultException 예외를 발생시킨다.
- 이처럼 예외가 발생할 수 있기에 try, catch를 통한 핸들링이 필요하다. Spring Data JPA에서는 값이 없을 경우 예외를 발생시키는 부분을 개선하였으며 null 혹은 Optional 객체를 리턴하도록 구현되어 있다.
TypedQuery<Member> list =
em.createQuery("select m from Member m", Member.class);
// 결과가 하나 이상일 것을 예상하여 getResultList를 통해 반환받음
List<Member> memberList = list.getResultList();
TypedQuery<Member> single =
em.createQuery("select m from Member m where m.id = 1L", Member.class);
// 결과가 하나일 것을 예상하여 getSingleResult를 통해 반환받음.
// 만약 결과가 2개 이상이거나 없을 경우 예외가 발생함.
Member singleMember = single.getSingleResult();
6. 파라미터 바인딩
- 이름 기준과 위치 기준으로 바인딩 하는 방법이 있다.
- 이름 기준으로 사용 시 쿼리에 ":" 구문을 사용하며, 위치 기준으로 사용 시 "?번호" 구문을 사용한다.
- 위치 기반 바인딩은 쿼리 중간에 조건이 하나 더 추가될 경우 쿼리에 사용한 번호가 밀려 에러를 유발할 수 있다. 이에따라 위치 기반보다는 이름 기준 바인딩이 권장된다.
* TypedQuery와 Query는 메서드 체이닝을 지원하기에 한번에 처리 가능하다.
// 이름 기준 파라미터 바인딩
TypedQuery<Member> query
= em.createQuery("select m from Member m where m.id = :id and m.username = :username", Member.class);
query.setParameter("username", "심승경");
query.setParameter("id", 1L);
Member singleMember = query.getSingleResult();
// 메서드 체이닝 방식
Member singleResult
= em.createQuery("select m from Member m where m.id = :id and m.username = :username", Member.class)
.setParameter("username", "심승경")
.setParameter("id", 1L)
.getSingleResult();
// 위치 기준 파라미터 바인딩
singleResult =
em.createQuery("select m from Member m where m.id = ?1 and m.username = ?2", Member.class)
.setParameter(1, 1L)
.setParameter(2, "심승경")
.getSingleResult();
7. 참고
- 자바 ORM 표준 JPA 프로그래밍 - 김영한
'백엔드 > JPA' 카테고리의 다른 글
[JPA] ConstraintViolationException 발생 원인 / 영속성 전이 (0) | 2023.05.17 |
---|---|
[JPA] JPQL 내부 조인, 외부 조인, 세타 조인 (0) | 2023.04.13 |
[JPA] 프로젝션 및 JPA 페이징 API (0) | 2023.04.13 |