contents

JPQL(Jakarta Persistence Query Language) 은 관계형 데이터베이스에 저장된 데이터를 검색하고 조작하는 데 사용되는 강력한 객체 지향 쿼리 언어입니다. 이는 자바의 객체-관계 매핑(ORM) 표준 명세인 JPA(Jakarta Persistence API) 의 핵심 부분입니다.

JPQL을 원시 데이터베이스 테이블 대신 자바 객체(엔티티)를 대상으로 작동하는, 이식성 높고 데이터베이스에 독립적인 SQL 버전이라고 생각할 수 있습니다.


JPQL이 해결하는 문제: SQL의 한계

왜 그냥 일반 SQL을 사용하지 않을까요? JPQL은 자바 개발자를 위해 두 가지 주요 문제를 해결하기 위해 만들어졌습니다.

  1. 데이터베이스 독립성 (이식성) 🐘: PostgreSQL, MySQL, Oracle과 같은 다른 데이터베이스들은 약간씩 다른 SQL 방언(dialect)과 함수를 가지고 있습니다. 만약 쿼리를 네이티브 SQL로 작성하면, 애플리케이션은 특정 데이터베이스에 종속됩니다. JPQL은 추상화 계층을 제공합니다. 표준 JPQL로 쿼리를 작성하면, JPA 프로바이더(Hibernate나 EclipseLink 등)가 설정된 데이터베이스에 맞는 정확한 SQL 방언으로 자동 번역해 줍니다. 이는 데이터 접근 계층의 이식성을 높여줍니다.

  2. 객체-관계 불일치: 개발자들은 객체, 클래스, 필드(예: firstName 필드를 가진 Customer 객체)의 관점에서 생각합니다. 데이터베이스는 테이블, 행, 열(예: first_name 열을 가진 customers 테이블)의 관점에서 생각합니다. JPQL은 객체 지향 도메인 모델을 사용하여 쿼리를 작성하게 함으로써 이러한 격차를 해소합니다. 이는 더 직관적이고 오류 발생 가능성을 줄여줍니다.


JPQL vs. SQL: 주요 차이점

특징 JPQL 네이티브 SQL
쿼리 대상 엔티티와 그 영속 필드. 테이블과 그 컬럼.
문법 클래스 이름과 필드 이름을 사용 (대소문자 구분). 테이블 이름과 컬럼 이름을 사용 (종종 대소문자 무시).
이식성 높음 (데이터베이스 독립적). 낮음 (특정 데이터베이스 방언에 따라 다를 수 있음).
객체 모델 엔티티 관계(@OneToMany 등)를 이해함. 객체 관계를 이해하지 못함.
예시 SELECT c FROM Customer c WHERE c.lastName = 'Doe' SELECT * FROM customers WHERE last_name = 'Doe'

핵심 문법 및 구조 📜

JPQL 쿼리는 SQL과 매우 유사하게 여러 절(clause)로 구성되지만, 객체 지향적인 초점을 맞춥니다.

SELECT

SELECT 절은 검색하려는 대상을 식별합니다.

FROM

FROM 절은 쿼리할 엔티티를 지정합니다. 중요한 점은 데이터베이스 테이블 이름이 아닌 엔티티 클래스 이름을 사용한다는 것입니다. 또한 쿼리 전체에서 사용될 별칭(alias)을 할당합니다.

-- "Customer"는 자바 클래스 이름이고, "c"는 별칭입니다.
FROM Customer c

WHERE

WHERE 절은 SQL에서와 마찬가지로 조건을 기반으로 결과를 필터링합니다. 별칭과 엔티티의 필드 이름을 사용합니다. 값을 안전하게 전달하기 위해 이름 기반 파라미터(콜론 :으로 시작)를 사용하는 것이 일반적입니다.

-- 특정 도시에 있는 고객 찾기
SELECT c FROM Customer c WHERE c.city = :cityParam

JOIN 절 🔗

JPQL은 엔티티에 정의된 관계(@OneToMany, @ManyToOne 등)를 활용하여 조인을 직관적으로 만듭니다. 객체 그래프를 직접 탐색할 수 있습니다.

기타 일반적인 절


코드에서 JPQL 실행 방법 ⚙️

자바 애플리케이션에서 JPA의 EntityManager를 사용하여 JPQL 쿼리를 실행합니다.

import jakarta.persistence.EntityManager;
import jakarta.persistence.TypedQuery;
import java.util.List;

// 'em'이 주입된 EntityManager 인스턴스라고 가정
public List<Customer> findCustomersByCity(String city) {
    // 1. JPQL 쿼리 문자열 정의
    String jpql = "SELECT c FROM Customer c WHERE c.city = :cityParam";

    // 2. Query 객체 생성
    TypedQuery<Customer> query = em.createQuery(jpql, Customer.class);

    // 3. 이름 기반 파라미터 설정
    query.setParameter("cityParam", city);

    // 4. 쿼리 실행 및 결과 가져오기
    List<Customer> customers = query.getResultList();

    return customers;
}

고급 개념

references