JPQL(Java Persistence Query Language)

JPQL은 Java의 ORM(Object Relational Mapping) 프레임워크인 JPA(Java Persistence API)에서 제공하는 쿼리 언어입니다. SQL과 비슷하지만, 데이터베이스 테이블이 아닌 자바 객체(Entity)를 대상으로 쿼리를 작성한다는 점이 특징입니다.


🧐 JPQL의 개념

  1. SQL과의 차이점
  • SQL은 데이터베이스 테이블과 컬럼을 직접 조회합니다.
    예: SELECT * FROM employees
  • JPQL은 자바 객체(Entity)와 속성을 기반으로 쿼리를 작성합니다.
    예: SELECT e FROM Employee e
  1. JPQL의 장점
  • 데이터베이스에 의존적이지 않음 → 특정 DBMS에 종속되지 않고, 객체 지향적인 설계가 가능합니다.
  • JPA가 JPQL을 SQL로 변환해 실행 → 유지보수성과 코드 일관성이 높아집니다.

🛠️ JPQL의 기본 구조

JPQL의 기본 문법은 SQL과 유사하지만, 엔티티(Entity)필드를 대상으로 작업합니다.

📌 기본 문법

SELECT [별칭] FROM [Entity 이름] [별칭] WHERE [조건]

📌 예제 코드

// 엔티티 클래스
@Entity
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
    private double salary;

    // Getters and Setters
}

// JPQL 사용 예시
TypedQuery<Employee> query = entityManager.createQuery(
    "SELECT e FROM Employee e WHERE e.salary > :minSalary", Employee.class);
query.setParameter("minSalary", 5000.0);
List<Employee> employees = query.getResultList();

💡 JPQL의 주요 특징

  1. 객체를 대상으로 쿼리 작성
  • JPQL은 SQL처럼 데이터베이스 테이블과 컬럼 이름을 사용하지 않습니다.
  • 대신, 엔티티와 엔티티의 필드 이름을 사용합니다.
  • 예: SELECT e FROM Employee e에서 Employee는 엔티티 클래스, e는 별칭입니다.
  1. 다양한 쿼리 지원
  • JPQL은 SELECT, UPDATE, DELETE 쿼리를 지원합니다.
  • 데이터 삽입은 JPA의 persist() 메서드를 사용합니다.
  1. 조인(Join) 지원
  • 엔티티 간의 관계를 이용해 조인을 작성할 수 있습니다.

  • 예:

    SELECT e FROM Employee e JOIN e.department d WHERE d.name = 'IT'
  1. JPQL 함수
  • JPQL은 기본적으로 SQL의 함수들을 제공합니다.
    • 예: UPPER(), LOWER(), CONCAT(), CURRENT_DATE()
  • 추가적으로 사용자 정의 함수를 사용할 수도 있습니다.

📋 JPQL 사용법과 코드 예시

1️⃣ SELECT 쿼리

// 모든 직원의 이름을 조회
TypedQuery<String> query = entityManager.createQuery(
    "SELECT e.name FROM Employee e", String.class);
List<String> employeeNames = query.getResultList();

2️⃣ 파라미터 바인딩

  • JPQL에서는 파라미터를 안전하게 전달하기 위해 Named Parameter를 사용합니다.
TypedQuery<Employee> query = entityManager.createQuery(
    "SELECT e FROM Employee e WHERE e.salary > :minSalary", Employee.class);
query.setParameter("minSalary", 5000.0);
List<Employee> result = query.getResultList();

3️⃣ JOIN

  • 엔티티 간의 관계를 이용해 조인을 작성할 수 있습니다.
TypedQuery<Employee> query = entityManager.createQuery(
    "SELECT e FROM Employee e JOIN e.department d WHERE d.name = :deptName", Employee.class);
query.setParameter("deptName", "IT");
List<Employee> result = query.getResultList();

4️⃣ UPDATE와 DELETE

// 급여 인상
entityManager.createQuery("UPDATE Employee e SET e.salary = e.salary * 1.1 WHERE e.department = :dept")
    .setParameter("dept", "IT")
    .executeUpdate();

// 직원 삭제
entityManager.createQuery("DELETE FROM Employee e WHERE e.name = :name")
    .setParameter("name", "John Doe")
    .executeUpdate();

🔍 JPQL 사용 시 주의사항

  1. SQL과 구분하기
  • SQL은 테이블과 컬럼 이름을 사용하지만, JPQL은 엔티티와 필드 이름을 사용해야 합니다.
  • 잘못된 예: SELECT e FROM employees e (SQL 스타일)
  • 올바른 예: SELECT e FROM Employee e
  1. 쿼리 결과 타입
  • JPQL 쿼리 결과는 엔티티 객체로 반환됩니다.
  • 원하는 컬럼만 가져오고 싶다면 DTO를 사용하거나, 원하는 데이터만 추출해야 합니다.
  1. 데이터베이스 의존성 제거
  • JPQL을 사용하면 DBMS 간 의존성이 줄어들지만, 특정 기능(예: DB 고유의 함수 사용)이 제한될 수 있습니다.
  1. Lazy Loading 주의
  • 관계가 설정된 엔티티를 조회할 때, 지연 로딩(Lazy Loading)으로 인해 성능 문제가 발생할 수 있습니다.
  • 필요에 따라 Fetch Join을 사용해 즉시 로딩(Eager Loading)으로 설정합니다.
    SELECT e FROM Employee e JOIN FETCH e.department

✅ JPQL 요약

항목설명
대상엔티티와 필드
문법SQL과 유사하지만 객체 지향적
장점DB 독립성, 코드 유지보수성 증가
주요 기능SELECT, JOIN, UPDATE, DELETE 쿼리 지원
주의사항엔티티 이름 및 필드 사용, Lazy Loading 성능 문제

QueryDSL을 사용하는 이유

QueryDSL은 JPQL의 한계를 극복하기 위해 등장한 도구입니다.

1️⃣ JPQL의 한계

  • 정적 쿼리 중심: JPQL은 주로 정적으로 작성된 쿼리를 사용하기 때문에 조건에 따라 달라지는 동적 쿼리를 작성하기가 어렵습니다.

  • 문자열 기반 작성: 쿼리를 문자열로 작성하다 보니, 오타나 오류를 실행 중에야 발견할 수 있어 유지보수가 까다롭습니다.

  • : 밑의 사진을 보면 SQL문법과 JPQL이 SELECT쿼리문을 사용하는 부분은 동일하지만 JPQL은 객체 지향적인 방식으로 주로 정적으로 작성된 쿼리를 사용합니다.

2️⃣ Criteria의 단점

  • 복잡한 문법: JPA에서 동적 쿼리를 작성할 때 Criteria API를 사용할 수 있지만, 코드가 장황하고 직관적이지 않아 읽기 어렵습니다.

3️⃣ QueryDSL의 장점

  • 타입 안전성: 쿼리를 자바 코드로 작성하기 때문에, 컴파일 시점에 오류를 발견할 수 있어 안정적입니다.
  • 동적 쿼리 작성 편의성: QueryDSL은 BooleanBuilder 등 간단한 API를 제공해 조건에 따라 유연하게 동적 쿼리를 작성할 수 있습니다.
  • 가독성 향상: 자바 코드와 쿼리가 통합되어, 직관적이고 간결한 코드 작성이 가능합니다.

참고한 블로그

코딩이랑 이것저것 - [JPA] Part 5 (객채지향 쿼리 언어 pt.1)


profile
다 먹어버릴거야!

0개의 댓글