@Query 어노테이션은 Spring Data JPA에서 JPQL(Java Persistence Query Language) 또는 네이티브 SQL 쿼리를 작성할 때 사용하는 어노테이션이다. 보통은 메서드 이름을 기반으로 쿼리를 자동으로 생성하는데, 복잡한 쿼리나 특정 요구사항이 있는 경우 직접 쿼리를 작성해야 할 때 사용된다.
@Query 어노테이션 기본 설명
- 어노테이션 위치: @Query는 Repository 인터페이스의 메서드 위에 붙인다.
- 쿼리 타입: JPQL과 네이티브 쿼리 두 가지를 사용할 수 있다. 기본은 JPQL로, JPA 엔티티를 대상으로 하는 쿼리이다. 네이티브 쿼리는 실제 데이터베이스에서 사용하는 SQL 쿼리를 직접 작성할 수 있다.
// 기본 JPQL 예시
@Query("SELECT t FROM Task t WHERE t.weather = :weather")
List<Task> findByWeather(@Param("weather") String weather);
위 코드는 Task라는 엔티티에서 weather라는 필드를 기반으로 데이터를 검색하는 쿼리이다. :weather는 파라미터를 의미하며, @Param을 통해 메서드 인자로 전달된 값을 사용한다.
@Query 문법 구조
1. SELECT 절: 어떤 엔티티(테이블)를 조회할지 지정한다. JPQL에서는 엔티티를 대상으로 쿼리를 작성한다.
SELECT t FROM Task t
- 여기서 Task는 엔티티 이름이며, t는 별칭이다. 즉, Task 엔티티에서 데이터를 조회할 때 t라는 별칭을 사용할 수 있다.
2. WHERE 절: 조건을 지정하는 부분이다. 여기서 쿼리에 사용할 필터링 조건을 정의한다.
WHERE t.weather = :weather
:weather는 파라미터를 의미하며, 메서드 인자에서 값을 전달받아 해당 값을 쿼리에 적용한다. 이런 방식으로 동적 파라미터를 사용할 수 있다.
3. @Param 어노테이션: @Param을 사용하여 메서드의 인자와 쿼리의 파라미터를 매칭시킨다.
@Query("SELECT t FROM Task t WHERE t.weather = :weather")
List<Task> findByWeather(@Param("weather") String weather);
여기서 @Param("weather")는 메서드 인자 weather와 쿼리의 :weather 파라미터를 매칭시킨다. 메서드 호출 시 넘겨준 값이 쿼리에서 사용된다.
네이티브 쿼리 사용
가끔 JPQL로는 해결되지 않는 복잡한 쿼리가 있을 때가 있다. 이럴 때 네이티브 SQL을 사용할 수 있다. 네이티브 SQL은 데이터베이스에서 바로 실행되는 쿼리이기 때문에 JPA가 아닌 실제 SQL 문법을 사용한다.
@Query(value = "SELECT * FROM tasks WHERE weather = :weather", nativeQuery = true)
List<Task> findByWeatherNative(@Param("weather") String weather);
여기서 nativeQuery = true를 사용하면 네이티브 SQL로 실행된다. 실제 데이터베이스에 있는 테이블명과 필드명을 직접 사용해야 한다.
여러 조건을 사용한 @Query 예시
@Query는 여러 조건을 조합하여 사용할 수 있다. 예를 들어, 두 가지 조건을 만족하는 데이터를 찾고 싶을 때는 AND 또는 OR을 사용할 수 있다.
@Query("SELECT t FROM Task t WHERE t.weather = :weather AND t.modifiedDate >= :date")
List<Task> findByWeatherAndDate(@Param("weather") String weather, @Param("date") LocalDate date);
위 예시는 weather 필드와 modifiedDate 필드 모두에 조건을 걸어 데이터를 필터링하는 방법이다. AND는 두 조건이 모두 참일 때만 데이터를 반환한다.
동적 쿼리 사용 (Optional 파라미터)
경우에 따라 파라미터를 선택적으로 사용할 수 있다. 이런 경우는 null 값을 체크하여 동적으로 쿼리를 변경하는 방식이다.
@Query("SELECT t FROM Task t WHERE (:weather IS NULL OR t.weather = :weather) AND (:date IS NULL OR t.modifiedDate >= :date)")
List<Task> searchTasks(@Param("weather") String weather, @Param("date") LocalDate date);
이 예시는 weather와 date 파라미터가 각각 null일 경우 조건을 무시하고, 그렇지 않으면 해당 조건을 적용하는 방식이다. 즉, weather가 없으면 모든 날씨 데이터를, date가 없으면 모든 날짜 데이터를 검색하는 동적 쿼리이다.
결론
@Query 어노테이션은 JPA에서 제공하는 강력한 기능으로, 복잡한 쿼리를 작성할 수 있게 해준다. 기본 메서드 이름으로는 처리하기 어려운 복잡한 로직이나 동적 쿼리를 처리할 때 유용하다. JPQL을 기본으로 하지만, 필요할 때 네이티브 SQL을 사용할 수도 있다. 메서드에 붙여 쿼리를 직접 작성하고, 파라미터를 통해 동적인 데이터 필터링을 구현할 수 있다.
이처럼 @Query는 유연한 쿼리 작성을 가능하게 해주는 매우 중요한 도구이다. 실무에서 다양한 쿼리 요구사항을 만족시키기 위해 자주 사용되는 기능이기 때문에 꼭 익혀두는 것이 좋다.
'SPRING&BOOT > JPA' 카테고리의 다른 글
CascadeType.REMOVE는 왜 위험할까? (1) | 2024.09.06 |
---|---|
중간 테이블을 사용하는 이유 (0) | 2024.09.02 |
JWT란? (0) | 2024.08.30 |
관계형 데이터베이스에서 중간 테이블의 중요성과 활용 방법 (0) | 2024.08.27 |
JPA 지연 로딩(Lazy Loading) (0) | 2024.08.27 |