Spring Data JPA는 메서드 이름만으로도 간단한 쿼리를 자동 생성해주지만, 복잡한 조건이나 조인을 처리하려면 JPQL(Java Persistence Query Language)과 @Query 어노테이션이 필요합니다.
JPQL 작성법과 @Query 사용 방법을 정리해보겠습니다.
1. JPQL이란?
JPQL은 SQL과 비슷하지만, 엔티티(Entity)를 대상으로 동작한다는 점이 다릅니다. 즉, SELECT u FROM User u
처럼 테이블이 아닌 엔티티 클래스 이름을 기준으로 작성합니다.
JPQL vs SQL
JPQL | SQL |
---|---|
SELECT u FROM User u WHERE u.age > 20 | SELECT * FROM users WHERE age > 20 |
엔티티 기준 | 테이블 기준 |
2. @Query 어노테이션 기본 사용법
JPA의 Repository 인터페이스에 @Query
를 사용하면 JPQL을 직접 작성할 수 있습니다.
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
@Query("SELECT u FROM User u WHERE u.email = :email")
Optional<User> findByEmail(@Param("email") String email);
}
주의할 점
- JPQL은 엔티티명.필드명으로 작성해야 합니다.
- SQL처럼
*
를 사용할 수 없습니다.SELECT u
또는SELECT u.name
처럼 명시해야 합니다.
3. @Query로 JOIN 처리하기
복잡한 연관 관계 쿼리는 JPQL의 JOIN 문법을 활용할 수 있습니다.
@Query("SELECT o FROM Order o JOIN o.user u WHERE u.name = :name")
List<Order> findOrdersByUserName(@Param("name") String name);
위 쿼리는 Order
와 User
가 연관관계(@ManyToOne 등)로 매핑되어 있어야 사용 가능합니다.
4. Native SQL 사용하기
JPQL로 표현하기 어려운 쿼리는 nativeQuery = true
옵션으로 Native SQL도 작성할 수 있습니다.
@Query(value = "SELECT * FROM users WHERE email LIKE %:keyword%", nativeQuery = true)
List<User> searchByEmail(@Param("keyword") String keyword);
단, Native SQL을 사용할 경우 반환 타입 매핑에 주의해야 합니다. Projection 또는 Interface 기반 DTO를 함께 활용하는 것이 좋습니다.
5. DTO 직접 조회 – new 키워드 활용
JPQL에서는 new
키워드를 사용해 직접 DTO 객체를 생성할 수 있습니다.
@Query("SELECT new com.example.dto.UserDto(u.id, u.name) FROM User u WHERE u.active = true")
List<UserDto> findActiveUsers();
DTO는 반드시 해당 필드들을 받는 생성자가 정의되어 있어야 하며, 패키지 경로까지 명시해야 합니다.
6. 정렬, 페이징도 함께
@Query
는 Pageable
과 함께 사용할 수 있습니다.
@Query("SELECT u FROM User u WHERE u.status = :status")
Page<User> findByStatus(@Param("status") String status, Pageable pageable);
JPQL 내부에는 ORDER BY
를 넣지 않아도 되고, 정렬은 PageRequest.of(...)
에서 처리 가능합니다.
7. 정리 및 실무 팁
- 단순 조회는 메서드 이름 기반으로, 복잡한 쿼리는 @Query로 처리
- JOIN, GROUP BY, 복잡한 조건은 JPQL 또는 Native SQL 활용
- 결과가 엔티티가 아닐 경우 DTO 매핑 시 new 키워드 또는 Projection 사용
- 쿼리가 길어질 경우 @Query 대신 Querydsl도 고려
'개발 > JAVA' 카테고리의 다른 글
[JAVA] JPA Fetch 전략 완벽 가이드 – Lazy vs Eager 실무 적용법 (0) | 2025.10.14 |
---|---|
[JAVA] Entity 연관관계 완전 정복 – 1:N, N:M, Cascade까지 실무 중심 정리 (0) | 2025.10.13 |
[JAVA] JPA Repository 메서드 쿼리 작성법 – 실무 중심 가이드 (0) | 2025.10.11 |
[JAVA] @Entity, @Id, @GeneratedValue 완벽 가이드 – JPA 기본부터 실무 팁까지 (0) | 2025.10.10 |
[JAVA] Spring Data JPA 소개와 기본 사용법 (0) | 2025.10.09 |