JPA

JPQL 문법 완벽 가이드: JPA를 위한 쿼리 작성법

초코너무조코 2025. 6. 5. 20:38
728x90

 

Java Persistence API(JPA)를 사용할 때 객체 지향 패러다임을 유지하면서 데이터베이스를 조회하기 위해서는 Java Persistence Query Language(JPQL) 를 이해해야 합니다. JPQL은 SQL과 유사하지만, 테이블이 아닌 엔티티와 그 관계를 대상으로 질의를 수행한다는 점이 특징입니다. 본 글에서는 JPQL의 핵심 문법과 실전 예제, 그리고 성능 최적화 팁까지 한 번에 정리해 보겠습니다.


1. JPQL 기본 구조

JPQL의 구문은 SQL과 유사하나, 주요 키워드와 대상이 엔티티임을 기억하세요.

// JPQL 기본 예시
String jpql = "SELECT m FROM Member m WHERE m.age > 20";

 

  설명
SELECT 반환할 엔티티(또는 필드) 지정
FROM 조회 대상 엔티티 지정
WHERE 조건식 작성
ORDER BY 정렬
GROUP BY / HAVING 그룹화, 그룹 조건

1.1 SELECT 절

  • 엔티티 전체: SELECT m FROM Member m
  • 특정 필드: SELECT m.username FROM Member m
  • 새 DTO: SELECT new com.example.dto.MemberDto(m.username, m.age) FROM Member m

1.2 WHERE 절

  • 비교 연산자: =, <, >, <=, >=, <>
  • BETWEEN, LIKE, IS NULL, MEMBER OF 등 사용 가능
SELECT m FROM Member m WHERE m.username LIKE '%kim%'

2. 경로 탐색(Path Expressions)과 조인

객체 그래프를 탐색하거나 연관 관계를 명시적으로 조인할 수 있습니다.

2.1 내부 조인 (Inner Join)

SELECT m FROM Member m JOIN m.team t WHERE t.name = '개발팀'

2.2 외부 조인 (Left/Right Outer Join)

SELECT m FROM Member m LEFT JOIN m.team t

2.3 컬렉션 조인

SELECT o FROM Order o JOIN o.orderItems i WHERE i.price > 10000

Tip: 필요에 따라 FETCH JOIN을 사용해 N+1 문제를 해결하세요.


3. 서브쿼리

JPQL은 FROM 절을 제외한 모든 곳에서 서브쿼리를 지원합니다.

SELECT m FROM Member m WHERE m.age > (
    SELECT AVG(m2.age) FROM Member m2
)

4. 그룹화와 집계 함수

SELECT t.name, COUNT(m) FROM Team t JOIN t.members m GROUP BY t.name HAVING COUNT(m) >= 3

집계 함수: COUNT, SUM, AVG, MAX, MIN


5. 타입 표현식(Type Expressions)과 다형성 쿼리

상속 관계 매핑 시 TYPE 또는 TREAT 키워드로 서브 타입을 다룰 수 있습니다.

SELECT i FROM Item i WHERE TYPE(i) IN (Book, Movie)

6. JPQL 함수

표준 함수뿐 아니라 방언(Dialect)별 사용자 정의 함수도 호출 가능합니다.

6.1 문자열 함수

  • CONCAT, SUBSTRING, TRIM, LOWER / UPPER

6.2 숫자 함수

  • ABS, MOD, SQRT

6.3 날짜/시간 함수 (JPA 2.2+)

  • CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP
SELECT FUNCTION('group_concat', m.username) FROM Member m

7. 파라미터 바인딩

7.1 이름 기반 파라미터

String jpql = "SELECT m FROM Member m WHERE m.username = :username";
query.setParameter("username", "kim");

7.2 위치 기반 파라미터 (Deprecated)

String jpql = "SELECT m FROM Member m WHERE m.username = ?1";

추천: 가독성과 유지보수를 위해 이름 기반 파라미터를 사용하세요.


8. 벌크 연산 (UPDATE, DELETE)

int count = em.createQuery("UPDATE Member m SET m.age = m.age + 1 WHERE m.age >= 20")
              .executeUpdate();

8.1 벌크 연산 시 주의 사항

  • 벌크 연산은 영속성 컨텍스트를 무시하고 바로 DB에 반영됩니다.
  • 영속성 컨텍스트 초기화(clear) 또는 flush 필요.
em.flush();
em.clear();

9. 네이티브 쿼리와 JPQL의 차이

구분 JPQL 네이티브 SQL
대상 엔티티 및 속성 테이블 및 컬럼
이식성 높음 낮음(DB 종속)
성능 최적화 페치 조인, 배치 사이즈 등 DB/Hibernate 튜닝
사용 목적 일반 조회 복잡한 DB 특화 기능, 성능 튜닝

10. 성능 최적화를 위한 팁

  1. 페치 조인(FETCH JOIN) 으로 지연 로딩 문제 해결
  2. 필요 시 DISTINCT 로 중복 제거
  3. 하이버네이트 전역 설정 hibernate.default_batch_fetch_size 로 컬렉션 배치 로딩
  4. 쿼리 캐시와 2차 캐시 적극 활용

결론

JPQL은 JPA를 사용하는 개발자라면 반드시 알아야 할 핵심 기술입니다. 객체 지향 모델에 맞춘 질의를 작성하면 유지보수성과 가독성이 크게 향상됩니다. 본 가이드를 통해 기본 문법부터 성능 최적화 팁까지 익혀 생산성을 높여보세요!

참고 자료

  • Java Persistence with Hibernate, 2nd Edition
  • 자바 ORM 표준 JPA 프로그래밍 – 김영한
  • Hibernate 공식 매뉴얼

 

728x90