개발놀이터
JPQL 초급 본문
*JPQL
-테이블이 아닌 객체를 대상으로 검색하는 객체 지향 쿼리
-SQL을 추상화해서 특정 데이터베이스 SQL에 의존X
-JPQL을 한마디로 정의하면 객체 지향 SQL
JPQL이 해결해야할 가장 큰 문제점 = 동적쿼리
그에 따른 해결책 = Criteria, Querydsl
Criteria의 특징
-문자가 아닌 자바코드로 JPQL을 작성할 수 있음
-JPQL 빌더 역할
-JPA 공식기능
-치명적인 단점 : 너무 복잡하고 실용성이 없다.
-Criteria대신 Querydsl 사용 권장
Querydsl의 특징
-문자가 아닌 자바코드로 JPQL을 작성할 수 있음
-JPQL 빌더 역할
-컴파일 시점에 문법 오류를 찾을 수 있음
-동적 쿼리 작성 편리함
-단순하고 쉬움
-실무 사용 권장
*JPQL 소개
-JPQL은 객체지향 쿼리 언어이다. 따라서 테이블을 대상으로 쿼리하는 것이 아니라 엔티티 객체를 대상으로 쿼리한다.
-JPQL은 SQL을 추상화해서 특정 데이터에비스 SQL에 의존하지 않는다.
-JPQL은 결국 SQL로 변환된다
*JPQL 문법
em.createQuery("select m from Member m where m.age > 20"), Member.class);
-엔티티와 속성은 대소문자를 구분한다. (Member, age)
-JPQL키워드는 대소문자를 구분하지 않는다. (select, from, where)
-엔티티 이름 사용, 테이블 이름이 아님(Member)
-엘리어스 필수 (as는 생략가능)
*TypeQuery vs Query
TypeQuery : 반환 타입이 명확할 때 사용
TypeQuery<Member> query = em.createQuery("select m from Member m"), Member.class); => Member엔티티에 대한 반환타입
Query : 반환 타입이 명확하지 않을 때 사용
Query query = em.createQuery("select m.username, m.age from Member m"); => username = String / age = int 타입이 명확하지 않음
*결과 조회 API
1. getResultList() : 결과가 하나 이상일 때, 리스트를 반환한다. 결과가 없으면 빈 리스트 반환
List<Member> findMember = em.createQuery("select m from Member m"), Member.class).getResultList();
2. getSingleResult() : 결과가 정확히 단 하나일 때 사용한다. 단일 객체 반환
Member findMember = em.createQuery("select m from Member m"), Member.class).getSingleResult();
getSingleResult를 주의해서 사용해야 하는 이유
-결과가 없으면 NoResultException이 발생하고
-둘 이상이면 NonUniqueResultException이 발생한다.
*파라미터 바인딩 - 이름기준, 위치기준
em.createQuery("select m from Member m where m.username = :username").setParameter("username", "member1"); 이런식으로 사용 마치 jdbc의 PreparedStatement를 사용 하듯이 사용하면 된다.
*프로젝션
-select 절에 조회할 대상을 지정하는 것
-프로젝션 대상 : 엔티티, 임베디드 타입, 스칼라 타입
ex)
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 -> 스칼라 타입 프로젝션 (다 때려박은거)
*조인
1. 내부조인 (inner join)
2. 외부조인 (outer join)
1. 내부조인
조인을 했을 때 하나라도 null이 있으면 결과로 출력을 안해줌
select m from Member m (inner) join m.team t -> SQL문과 다른 점은 엔티티를 대상으로 쿼리를 한다는 것
2. 외부조인
조인 했을 때 null이 있어도 결과로 출력해줌
select m from Member m left (outer) join m.team t
cf) on 절
조인을 할때 조인 대상을 필터링해준다.
select m from Member m left (outer) join m.team t on t.name = 'teamA' -> 팀이름이 teamA인 튜플을 골라준다
*서브 쿼리
JPQL에서도 서브 쿼리를 지원한다. 단 from 절에서의 서브쿼리는 지원하지 않는다.
select m from Member m where m.age (select avg(m2.age) from Member m2)
서브쿼리 지원 함수
-exists(subquery) : 서브쿼리에 결과가 존재하면 참
select m from Member m left join m.team t where exists(select t from t where t.name = 'teamA')
-all(subquery) : 모두 만족하면 참
select o from Order o where o.orderAmount > all(select p.stockAmount from Product p)
-any, some(subquery) : 조건을 하나라도 만족하면 참
select m from Member m where m.team = any(select t from Team t)
-in(subquery) : 서브쿼리의 결과 중 하나라도 같은 것이 있으면 참
JPA 서브쿼리의 한계
-JPA는 where, having 절에서만 서브쿼리 사용 가능
-select 절도 가능 (하이버네이트에서 지원)
-from 절의 서브 쿼리는 현재 JPQL에서 불가능 (조인으로 풀 수 있으면 풀어서 해결)
*조건식 - case문
-기본 case문
select case when m.age <= 10 then '학생요금' when m.age >= 60 then '경로요금' else '일반요금' end from Member m
-단순 case문
select case t.name when 'teamA' then '인센티브110%' when 'teamB' then '인센티브120%' else '인텐티브105%' end from Team t
-coalesce : 하나씩 조회해서 null이 아니면 반환
select coalesce(m.name, '이름 없는 회원') from Member m
'JPA > JPA' 카테고리의 다른 글
JPA를 활용한 (XToOne) Restful API설계 (0) | 2021.09.13 |
---|---|
JPQL 중급 (0) | 2021.08.26 |
값 타입 (0) | 2021.08.26 |
지연로딩과 즉시로딩 (프록시) (0) | 2021.08.24 |
JPA 상속관계 매핑 (0) | 2021.08.23 |