객체지향 쿼리 언어

JPA 에서 쓰이는 sql과 비슷한 JPQL(Java Persistence Query Language) 을 알아 보자

Posted by Jong-in Kim on 2017. 1. 23 오전 9:47

1 JPQL 소개

JPQL(Java Persistence Query Language) : 엔티티 객체를 조회하는 객체지향 쿼리.

  • JPQL은 SQL을 추상화해서 특정 데이터베이스에 의존하지 않는다.
  • JPQL은 객체지향 쿼리 언어다. 테이블X 엔티티O
  • JPQL은 결국 SQL로 변환된다.

 

1.1 기본문법

JPQL도 SQL과 비슷하게 SELECT, UPDATE, DLEETE 문을 사용(INSERT는 EntityManager.persist() 사용)

  • 대소문자 구분 : 엔티티와 속성은 대소문자 구분(ex : Member, username). 반면 SELECT, FROM, AS 같은 JPQL 키워드는 대소문자를 구분하지 않음
  • 엔티티 이름 : @Entity(name="XXX")로 지정하거나 지정안할시 클래스명을 기본으로 사용
  • 별칭은 필수 JPQL 표준은 필수 HQL(Hibernate Query Language)는 생략 가능.

 

1.2 쿼리 API

반환타입을 명확히 할수 있는 TypeQuery와

 

명확히 지정할 수 없을땐 Query를 사용하면 됨

 

1.3 파라미터 바인딩

이름 기준

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);

 

1.4 페이징 API

페이징 API - MySQL 방언

 

SELECT
  M.ID AS ID,
  M.AGE AS AGE,
  M.TEAM_ID AS TEAM_ID,
  M.NAME AS NAME
FROM
  MEMBER M
ORDER BY
  M.NAME DESC LIMIT ?, ?

 

페이징 API - Oracle 방언


SELECT * FROM
  ( SELECT ROW_.*, ROWNUM ROWNUM_
   FROM
      ( SELECT
          M.ID AS ID,
          M.AGE AS AGE,
          M.TEAM_ID AS TEAM_ID,
          M.NAME AS NAME
       FROM MEMBER M
       ORDER BY M.NAME
       ) ROW_
   WHERE ROWNUM <= ?
  )
WHERE ROWNUM_ > ?

 

 

1.5 집합과 정렬

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

 

 

1.6 조인

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

한계: 세타 조인시은 내부 조인만 사용할 수 있다.

페치 조인

  • 엔티티 객체 그래프를 한번에 조회하는 방법
  • 별칭을 사용할 수 없다.
  • JPQL: select m  from Member m join fetch m.team
  • SQL: SELECT  M.*, T.* FROM MEMBER T INNER JOIN TEAM T ON M.TEAM_ID=T.ID

예시

최적화를 위해 글로벌 로딩 전략을 즉시 로딩으로 설정하면 애플리케이션 전체에서 항상 즉시 로딩이 일어난다. 물론 일부는 빠를 수는 있지만 전체로 보면 사용하지 않는 엔티티를 자주 로딩하므로 오히려 성능에 악영향을 미칠 수 있다. 따라서 글로벌 로딩 전략은 될 수 있으면 지연 로딩을 사용하고 최적화가 필요하면 페치 조인을 적용하는 것이 효과적이다.

 

1.7 JPQL 기타

  • 서브 쿼리 지원 (from절에서 사용안됨)
  • EXISTS, IN
  • BETWEEN, LIKE, IS NULL

 

JPQL 기본 함수

  • CONCAT 문자열 합침
  • SUBSTRING 문자열 자름
  • TRIM 빈공간제거
  • LOWER, UPPER 소문자로, 대문자로 치환
  • LENGTH 길이를 구함
  • LOCATE 검색위치부터 문자를 검색 1부터 시작 못찾으면 0반환
  • ABS 절대값, SQRT 제곱근, MOD 나머지
  • SIZE 컬렉션크기 구함, INDEX 컬렉션의 위치값 구함(JPA 용도)

 

CASE 식

1.8 Named 쿼리: 정적 쿼리

  • 미리 정의해서 이름을 부여해두고 사용하는 JPQL
  • 어노테이션, XML에 정의
  • 애플리케이션 로딩 시점에 초기화 후 재사용
  • 애플리케이션 로딩 시점에 쿼리를 검증

'카테고리'의 글 목록