📌 JPQL이란?
- 데이터베이스에 질의(Query)를 실행하기 위해 사용하는 객체지향 쿼리 언어
- 테이블/컬럼이 아니라 엔티티/필드를 대상으로 질의
❓ JPQL이 왜 필요할까?
em.find()나 연관관계 탐색만으로는 조건 기반 조회가 어렵기 때문에,🔁 JPA가 지원하는 질의 방식
| 방식 | 쓰임새 | 장점 | 단점 |
|---|---|---|---|
| JPQL | 정적/일반 쿼리 | DB 독립적, 객체지향적 | 동적 조건이 많아지면 가독성 저하 |
| QueryDSL | 동적 쿼리 | 타입 안전, 가독성/유지보수 좋음 | 의존성 추가 필요 |
| Criteria | 코드 기반 JPQL | 표준 API | 너무 장황해 실무 선호도 낮음 |
| Native SQL | DB 종속 기능 | 성능/특화 기능 활용 | 이식성 낮음, 엔티티 그래프 이점 적음 |
🗄️ JPQL의 등장 배경
em.find() → 엔티티 그래프 탐색(tutor.getCompany())📌 예시 코드:
String jpql = "SELECT p FROM Product p WHERE p.price > :minPrice";
List<Product> products = em.createQuery(jpql, Product.class)
.setParameter("minPrice", 1000)
.getResultList();
SELECT p FROM Product p → SQL의 SELECT * FROM product와 대응✨ JPQL 특징
🧰 JPQL vs SQL
| 특징 | JPQL | SQL |
|---|---|---|
| 대상 | Entity & Field | Table & Column |
| 표현 방식 | 객체지향 | 관계형 |
| DB 독립성 | 높음 | 특정 DB 종속 |
| 호출 방식 | EntityManager.createQuery() | 직접 DB 연결 |
✍️ JPQL 기본 문법 스냅샷
🔎 기본 조회
String jpql = "select p from Product p where p.price > :minPrice";
List<Product> list = em.createQuery(jpql, Product.class)
.setParameter("minPrice", 1000)
.getResultList();
:minPrice 권장(인젝션/오타 예방)🤝 조인 & 패치 조인(지연로딩 최적화)
// 일반 조인
select o from Order o join o.member m where m.name = :name
// 패치 조인(연관 엔티티를 한 번에 로딩)
select o from Order o join fetch o.items
N+1 방지,🎯 프로젝션(뭘 뽑을 것인가)
// 엔티티
select m from Member m
// 스칼라
select m.name, m.age from Member m
// DTO
select new com.example.MemberDto(m.name, m.age) from Member m
🧮 그룹/정렬/페이징
select d.name, count(e) from Department d join d.employees e
group by d.name having count(e) >= :min
// 페이징
query.setFirstResult(0).setMaxResults(20);
🗃️ 동적 쿼리란?
- 실행 시점에 조건/값에 따라 변하는 SQL Query 작성 & 실행 방식
💡 JPQL 지원 문법
SELECT, WHERE, GROUP BY, HAVING, JOIN 등 사용 가능📌 예시 코드:
String jpql = "SELECT p FROM Product p WHERE 1=1";
if (name != null) {
jpql += " AND p.name = :name";
}
if (price != null) {
jpql += " AND p.price = :price";
}
🌀 JPQL 동적 쿼리의 한계
🧠 요약 정리
| 구분 | 핵심 내용 |
|---|---|
| 📚 JPQL 정의 | 객체지향 쿼리 언어, 테이블/컬럼이 아닌 엔티티/필드를 대상으로 작성 |
| 🔹 JPA의 Query 지원 | ① JPQL (객체지향 쿼리) ② QueryDSL (동적 쿼리 지원) ③ JPA Criteria (복잡, 잘 안 씀) ④ Native SQL (DB 종속 쿼리 필요 시) |
| 📌 등장 배경 | em.find() 및 연관관계 탐색만으로 조건 검색 불가 → 조건 기반 SQL 필요 → JPQL 등장 |
| 💻 예시 코드 | SELECT p FROM Product p WHERE p.price > :minPrice → 최소 가격 이상 상품 조회 |
| ✨ 특징 | - 엔티티 중심(객체 대상) - SQL 추상화 → DB 독립적 - 영속성 컨텍스트 활용 가능 - 타입 안정성 제공 |
| 🔄 JPQL vs SQL | JPQL: Entity & Field, 객체지향, DB 독립적, EntityManager.createQuery()SQL: Table & Column, 관계형, DB 종속, 직접 DB 연결 |
| ⚙️ 동적 쿼리 | 실행 시 조건/값에 따라 변하는 SQL 작성/실행 예: if (name != null) jpql += " AND p.name = :name"; |
| 🚨 동적 쿼리 한계 | - 정적 쿼리에 최적화 - 문자열 직접 조합 필요 - 가독성/유지보수 어려움 - 컴파일 시 오류 검증 불가 - 조건 많아질수록 복잡 |