티스토리 뷰

Development/jpa

[JPA] JPQL

Dev.다니엘 2021. 8. 8. 09:55

자바 ORM 표준 JPA 프로그래밍 - 기본편

JPQL

기본 문법

  • select m from Member m where m.age > 18
  • 엔티티와 속성은 대소문자를 구분한다. (Member, age)
  • JPQL 키워드는 대소문자를 구분하지 않는다.(SELECT, FROM, where)
  • 엔티티 이름 사용, 테이블 이름이 아님(Member)
  • 별칭(alias)는 필수(여기서는 Member의 m), as는 생략가능

집합과 정렬

  • select COUNT(m), SUM(m.age)... from Member m
  • GROUP BY, HAVING 지원
  • ORDER BY 지원

TypeQuery, Query

  • TypeQuery: 반환 타입이 명확할 때 사용
  • Query: 반환 타입이 명확하지 않을 때 사용
TypeQuery<Member> query 
            = em.createQuery("select m from Member M", Member.class);

Query<Member> query 
            = em.createQuery("select m from Member M");

결과 조회 API

  • query.getResultList(): 결과가 하나 이상일 때, 리스트 반환.
    • 결과가 없으면 빈 리스트 반환
  • query.getSingleResult(): 결과가 정확히 하나, 단일 객체 반환
    • 결과가 없으면: javax.persistence.NoResultException(값이 없으면 error를 던져 별로임)
    • 둘 이상이면: javax.persistence.NonUniqueResultException

파라미터 바인딩

//이름 기반 파라미터 바인딩
Member member = em.createQuery("select m from Member M where m.name = :username", Member.class);
        .setParameter("username", "daniel")
        .getSingleResult();

//위치 기반 파라미터 바인딩(사용 X)
Member member = em.createQuery("select m from Member M where m.name = ?1", Member.class);
        .setParameter(1, "daniel")
        .getSingleResult();

프로젝션

  • select 절에 조회할 대상을 지정하는 것
  • 프로젝션 대상: 엔티티, 임베디드 타입, 스칼라 타입(숫자, 문자 등 기본데이터 타입)
  • select m from Member m → 엔티티 프로젝션
  • select m.team Member m → 엔티티 프로젝션
  • select m.address Member m → 임베디드 타입 프로젝션
  • select m.username, m.age from Member m → 스칼라 타입 프로젝션
  • DISTINCT로 중복 제거 가능

프로젝션 - 여러 값으로 조회

  • select m.username, m.age from Member m
  • Query 타입으로 조회
  • Object[] 타입으로 조회
  • new 명령어로 조회
    • 단순 값을 DTO로 바로 조회: select new jpabook.jpql.UserDTO(m.username, m.age) from Member m
    • 패키지명을 포함한 전체 클래스 명 입력
    • 순서와 타입이 일치하는 생성자 필요

페이징 API

  • setFirstResult(int startPosition): 조회 시작 위치(0부터 시작)
  • setMaxResult(int maxResult): 조회할 데이터 수
  • 방언(Dialect)를 이용해서 여러 데이터베이스와 호환

조인

  • 내부조인: 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 절

  • ON절을 활용한 조인(JPA 2.1 부터 지원)
    • 조인 대상 필터링
    • select m.t from Member m left join m.team t = on t.name = 'A'
    • 연관관계 없는 엔티티 외부 조인(하이버네이트 5.1부터)
    • select m, t from Member m left join Team t on m.username = t.name

서브 쿼리

  • [NOT] EXIST(subquery): 서브쿼리에 결과가 존재하면 참
    • [ALL | ANY | SOME] (subquery)
    • ALL: 모두 만족하면 참
    • ANY, SOME: 같은 의미, 조건을 하나라도 만족하면 참
  • [NOT] IN (subquery): 서브쿼리의 결과 중 하나라도 같은 것이 있으면 참
  • 한계
    • JPA는 where, having 절에서만 서브 쿼리 사용 가능
    • select 절 서브쿼리는 하버네이트에서 지원함
    • from 절 서브쿼리는 현재 jpql에서는 불가능(join으로 풀 수 있으면 풀어서 해결)

JPQL 타입 표현

  • 문자: 'HELLO WORLD'
  • 숫자: 10L(long), 10D(Double), 10F(Float)
  • Boolean: TRUE, FALSE
  • ENUM: test.MemberType.Member(패키지명 포함)
  • 엔티티 타입: TYPE(m) = Member(상속 관계에서 사용)

조건식 - 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 '팀A' then '인센티브110%'
        when '팀B' then '인센티브120%'
              else '인센티브105%'
   end
 from Team t

COALESCE: 하나씩 조회해서 null이 아니면 반환

-- 사용자 이름이 없으면 이름 없는 회원을 반환
select coalesce(m.username, '이름 없는 회원') from Member m

NULLIF: 두 값이 같으면 null 반환, 다르면 첫번째 값 반환

-- 사용자 이름이 '관리자'면 null을 반환하고 나머지는 본인의 이름을 반환
select NULLIF(m.username, '관리자') from Member m

JPQL 기본함수

  • CONCAT(문자열 합치기)
  • SUBSTRING(문자열 자르기)
  • TRIM(공백제거)
  • LOWER, UPPER(대소문자)
  • LENGTH(길이)
  • LOCATE(위치 반환)
  • ABS, SQRT, MOD(절댓값, 제곱근, 나머지)
  • SIZE, INDEX(JPA 용도)

사용자 정의 함수 호출

  • 하이버네이트는 사용전 방언에 추가해야한다.
  • 사용하는 DB 방언을 상속받고, 사용자 정의 함수를 등록한다.
select function('group_concat', i.name) from Item i
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함