🧠 1. JPQL이란?
- JPQL(Jakarta Persistence Query Language)은 엔티티 객체 중심 쿼리 언어로, SQL과 거의 동일하지만 테이블이 아닌 엔티티를 기반으로 작성됨 jakarta.ee+2en.wikipedia.org+2thorben-janssen.com+2.
예시:— Author 엔티티를 객체 지향적으로 조회 thorben-janssen.com
SELECT a FROM Author a ORDER BY a.firstName, a.lastName
🔄 2. 동적 쿼리 (Dynamic Query)
- JPQL은 정적이므로 QueryDSL, Criteria API, SpEL 기반 @Query 등을 통해 런타임 시 동적 조립함 baeldung.com+9medium.com+9thorben-janssen.com+9.
- 예시 (SpEL 사용):active 값이 null이면 해당 조건 건너뜀
-
@Query("SELECT u FROM User u WHERE (:active IS NULL OR u.active = :active)")
List<User> findByActive(@Param("active") Boolean active);
📘 3. 기본 문법
문법예시
| SELECT | SELECT m FROM Member m |
| WHERE | WHERE m.age > 20 |
| GROUP BY / HAVING | GROUP BY m.team HAVING COUNT(m) > 3 |
| ORDER BY | ORDER BY m.name DESC |
| UPDATE | UPDATE Member m SET m.status = 'INACTIVE' WHERE m.id = :id |
| DELETE | DELETE FROM Member m WHERE m.deleted = true |
🎯 4. 반환 타입 및 결과
- 단일 객체: getSingleResult()
- 리스트: getResultList()
- DTO 생성: SELECT new com.example.dto.MemberDto(m.name, m.age) FROM Member m(예시로 DTO 생성자를 호출하여 결과 매핑) medium.com+2thorben-janssen.com+2en.wikipedia.org+2
TypedQuery<MemberDto> q = em.createQuery( "SELECT new com.example.dto.MemberDto(m.name, m.age) FROM Member m", MemberDto.class);
List<MemberDto> dtos = q.getResultList();
🧩 5. 파라미터 바인딩
- 이름 기반: :name
- 위치 기반: ?1, ?2 등
@Query("SELECT m FROM Member m WHERE m.name = :name")
List<Member> findByName(@Param("name") String name);
📦 6. Embedded Type
- @Embeddable, @Embedded 사용 시 내장 값 객체에 필드 경로 지정 가능 vladmihalcea.com+15baeldung.com+15discourse.hibernate.org+15javacodegeeks.com+1openjpa.apache.org+1— 내장 타입 접근 경로로 쿼리 가능
@Embeddable
public class Address {private String city; /*...*/}
@Entity
public class Member { @Embedded Address address; }
// JPQL 예시 SELECT m FROM Member m WHERE m.address.city = :city
@Embeddable
public class Address {private String city; /*...*/}
@Entity
public class Member { @Embedded Address address; }
// JPQL 예시 SELECT m FROM Member m WHERE m.address.city = :city
📐 7. 프로젝션 (Projection)
- 엔티티: SELECT m FROM Member m
- 필드/embedded: SELECT m.address FROM Member m
- DTO:
- 덜 필요할 경우 Tuple 인터페이스도 활용 가능 medium.com+11en.wikipedia.org+11thorben-janssen.com+11thorben-janssen.com+1vladmihalcea.com+1
SELECT new com.example.dto.MemberDto(m.name, m.age) FROM Member m
📊 8. 페이징 (Paging)
- Spring Data JPA:
- 자동 countQuery 포함, Pageable 파라미터 활용 baeldung.com+2medium.com+2medium.com+2
@Query("SELECT u FROM User u")
Page<User> findAll(Pageable pageable);
🔗 9. Join
- 내부 조인: JOIN m.team t
- 왼쪽 외부 조인: LEFT JOIN m.team t
- 세타 조인(비연관 조인): FROM Member m, Team t WHERE m.name = t.name
- 페치 조인: JOIN FETCH m.team
- 추가 ON 조건: JPA 2.1 이상에서 사용 가능 vladmihalcea.comvladmihalcea.comthorben-janssen.com
🔁 10. CASE 식
SELECT CASE WHEN m.age >= 60 THEN 'Senior' WHEN m.age >= 30 THEN 'Adult' ELSE 'Junior' END FROM Member m
- 조건문 로직을 JPQL 내장하여 다양한 라벨링 가능
🛠 11. 함수 (Functions)
- 문자열: CONCAT(m.name, '님'), SUBSTRING(m.name, 1, 3)
- 수치: ABS(m.balance), SIZE(m.orders)
- 날짜/시간: CURRENT_DATE, CURRENT_TIME
- SQL/native 함수:
SELECT function('group_concat', t.name) FROM Post p JOIN p.tags t GROUP BY p.id
✅ 블로그용 요약 테이블
주제설명
| JPQL 개념 | 엔티티 기반 객체 지향 쿼리 |
| 동적 쿼리 | QueryDSL, Criteria, SpEL 이용 |
| 기본 문법 | SELECT/WHERE/JOIN 등 SQL 유사 |
| 반환 타입 | 단일 / 리스트 / DTO |
| 파라미터 바인딩 | 이름 방식, 위치 방식 |
| Embedded | 내장 타입 필드 접근 |
| 프로젝션 | 엔티티/embedded/DTO/Tuple |
| 페이징 | Pageable, Page 객체 |
| Join | 내부, 외부, 페치, ON 조인 |
| CASE | 조건 분기 표현 |
| 함수 | 문자열, 수치, 날짜, SQL 함수 |
🔗 출처 링크
- JPQL 개요 · Jakarta Persistence Query Language medium.com+1discourse.hibernate.org+1vladmihalcea.com+5thorben-janssen.com+5openjpa.apache.org+5discourse.hibernate.org+11en.wikipedia.org+11jakarta.ee+11
- Embedded 예시 · Baeldung, GeeksforGeeks geeksforgeeks.org+2baeldung.com+2baeldung.com+2
- 프로젝션 & DTO · Thorben Janssen thorben-janssen.com+1thorben-janssen.com+1
- 페이징 & 동적 쿼리 · Baeldung, Medium
- SQL 함수 호출 · Vlad Mihalcea medium.com+2vladmihalcea.com+2vladmihalcea.com+2
'부트캠프' 카테고리의 다른 글
| Spring Boot, H2, 그리고 JDBC (1) | 2025.06.23 |
|---|---|
| AOP(관점 지향 프로그래밍) (0) | 2025.06.12 |
| StringBuilder (1) | 2025.05.14 |
| SQL 달리기반 문제 (0) | 2025.03.28 |
| SQL 걷기반 문제 (0) | 2025.03.26 |