DEV ℧ Developer Diary

[JPA] JPQL - 기본 문법과 기능

해당 포스트는 인프런 김영한님의 자바 ORM 표준 JPA 프로그래밍 - 기본편 을 듣고 정리한 글입니다.

JPQL - 기본 문법과 기능

JPQL

소개

  • JPQL은 객체지향 쿼리 언어다.따라서 테이블을 대상으로 쿼리하는 것이 아니라 엔티티 객체를 대상으로 쿼리한다.
  • JPQL은 SQL을 추상화해서 특정데이터베이스 SQL에 의존하지 않는다.
  • JPQL은 결국 SQL로 변환된다.

JPQL

JPQL 문법

개요

  • select m from Member as m where m.age > 18
  • 엔티티와 속성은 대소문자 구분O (Member, age)
  • JPQL 키워드는 대소문자 구분X (SELECT, FROM, where)
  • 엔티티 이름 사용, 테이블 이름이 아님(Member)
  • 별칭은 필수(m) (as는 생략가능)

예시

select_문 :: =
    select_절
    from_절
    [where_절]
    [groupby_절]
    [having_절]
    [orderby_절]

update_문 :: = update_절 [where_절]
delete_문 :: = delete_절 [where_절]

update, delete는 벌크현상이라해서, 여러건을 한번에 업데이트를 치도록 JPA가 쿼리를 날린다.

집합과 정렬

  • GROUP BY, HAVING
  • ORDER BY
select
 COUNT(m), //회원수
 SUM(m.age), //나이 
 AVG(m.age), //평균 나이
 MAX(m.age), //최대 나이
 MIN(m.age) //최소 나이
from Member m

TypeQuery, Query

  • TypeQuery: 반환 타입이 명확할 때 사용
TypedQuery<Member> query1 = entityManager.createQuery("SELECT m FROM Member m", Member.class);
TypedQuery<String> query2 = entityManager.createQuery("SELECT m.username FROM Member m", String.class);

query1, query2 필드를 보면, m으로 컬럼을 호출해 Member.class로 반환하거나, String 타입인 m.username만 쿼리를 반환한다. 이렇게 반환값이 하나로 분명할 경우에는 TypeQuery를 사용할 수 있다.

  • Query: 반환 타입이 명확하지 않을 때 사용
Query query3 = entityManager.createQuery("SELECT m.username, m.age FROM Member m");

String 타입인 m.username와 int 타입인 m.age가 같이 반환되어 반환 타입이 특정되지 않을 경우에는 Query를 사용해서 쿼리값을 반환받는다.

결과 조회

  • query.getResultList(): 결과가 하나 이상일 때, 리스트 반환

    • 결과가 없으면 빈 리스트 반환
  • query.getSingleResult(): 결과가 정확히 하나, 단일 객체 반환

    • 결과가 없으면: javax.persistence.NoResultException
    • 둘 이상이면: javax.persistence.NonUniqueResultException

getResultList()는 무조건 빈 List를 반환하기 때문에 NPE(NullPointException)의 위험이 없다, 하지만 getSingleResult()의 경우 무조건 객체가 하나일 경우에만 반환하고 결과가 없거나 둘일경우 예외를 반환하기 때문에 주의해서 코드를 작성해야 한다.

파라미터 바인딩 - 이름 기준, 위치 기준

JPQL에서는 파라미터를 지정해 줄 수 있다.

/* 파라미터 바인딩 */
TypedQuery<Member> query = entityManager.createQuery("SELECT m FROM Member m WHERE m.username = :username", Member.class);
query.setParameter("username", "member1");
Member member1 = query.getSingleResult();
System.out.println("member1 : " + member1.getUsername());
/* SELECT
        m
    FROM
        Member m
    WHERE
        m.username = :username */ select
            member0_.id as id1_0_,
            member0_.age as age2_0_,
            member0_.TEAM_ID as team_id4_0_,
            member0_.username as username3_0_
        from
            Member member0_
        where
            member0_.username=?

member1 : member1