코딩마을방범대
[Java] @Query 어노테이션 본문
728x90
JPA가 제공하는 쿼리 메서드는 단순한 CRUD 기능이 가능하여 편리함을 제공하기는 하지만,
복잡한 조건을 처리해야하는 경우에는 한계가 있다.
이럴 때 사용하는 것이 @Query 어노테이션이다.
JPA 쿼리 메서드의 정의는 아래 링크를 통해 확인 가능하다.
@Query
기본적인 CRUD 메서드 외에 추가적인 쿼리가 필요한 경우 사용할 수 있다.
JPQL(Java Persistence Query Language) 또는 네이티브 SQL을 사용하여 쿼리를 정의할 수 있다.
@Query 어노테이션의 속성
속성명 | 설명 |
value | JPQL 또는 네이티브 SQL 쿼리를 정의함 |
nativeQuery | true로 설정하면 네이티브 SQL 쿼리를 사용할 수 있음 |
countQuery | 페이징 처리를 위한 카운트 쿼리를 별도로 정의할 수 있음 |
네이티브 SQL이란?
특정 데이터베이스 시스템에 최적화된 SQL 쿼리를 의미
데이터베이스 벤더(예: Oracle, MySQL, PostgreSQL 등)가 제공하는 고유한 SQL 문법과 기능을 사용하는 것
장점: 데이터베이스 고유 기능을 활용할 수 있어 복잡한 쿼리를 작성할 수 있음
단점: 데이터베이스에 종속적이므로 데이터베이스를 변경할 경우 쿼리를 수정해야 함
@Query와 JpaRepository의 차이점
@Query | JpaRepository | |
쿼리 작성 방식 | JPQL(Java Persistence Query Language) 또는 SQL을 직접 작성하여 쿼리를 정의할 수 있음 | 메서드 이름 규칙을 따라 쿼리를 자동으로 생성함 |
쿼리 복잡성 | 복잡한 쿼리를 작성할 수 있음 | 상대적으로 단순함 |
쿼리 최적화 | 직접 작성한 쿼리를 최적화할 수 있음 | JPA 구현체가 최적화함 |
쿼리 재사용성 | 정의한 쿼리를 다른 메서드에서 재사용할 수 있음 | 재사용하기 어려움 |
쿼리 가독성 | JPQL 또는 SQL을 직접 작성하므로 쿼리의 가독성이 높음 | 가독성이 상대적으로 낮음 |
SQL과 JPQL의 차이점
SQL | JPQL | |
대상 객체 | 데이터베이스의 테이블 | 엔티티 객체 |
추상화 수준 | 데이터베이스의 물리적인 구조에 의존적 | 객체 지향적인 추상화 수준을 가지고 있어 데이터베이스의 물리적인 구조에 독립적 |
쿼리 작성 방식 | 테이블 이름, 컬럼 이름 등을 직접 명시해야 함 | 엔티티 이름과 엔티티의 필드 이름을 사용하여 쿼리를 작성 |
데이터 타입 | 데이터베이스의 데이터 타입을 사용 | 자바 객체의 데이터 타입을 사용 |
쿼리 실행 과정 | 데이터베이스에 직접 쿼리를 전달하여 실행 | JPA 구현체가 JPQL을 SQL로 변환하여 데이터베이스에 전달 |
사용 예제
1. 기본적인 JPQL 쿼리 사용
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
@Query("SELECT u FROM User u WHERE u.email = :email")
User findByEmail(@Param("email") String email);
}
2. 복잡한 쿼리 사용
@Repository
public interface OrderRepository extends JpaRepository<Order, Long> {
@Query("SELECT o FROM Order o " +
"WHERE o.customer.name = :name " +
"AND o.status = :status " +
"ORDER BY o.createdDate DESC")
List<Order> findOrdersByCustomerNameAndStatus(@Param("name") String name, @Param("status") OrderStatus status);
}
3. 네이티브 SQL 사용
네이티브 SQL 쿼리에서는 순서 기반 파라미터 바인딩을 사용한다.
즉, 물음표 ?1, ?2 등으로 파라미터를 표현하고, 메서드 파라미터 순서대로 바인딩된다.
(네이티브 SQL 쿼리에서는 @Param 어노테이션을 사용할 필요가 없음)
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
@Query(value = "SELECT * FROM users WHERE email = ?1", nativeQuery = true)
User findByEmail(String email);
}
4. 파라미터 바인딩
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
@Query("SELECT p FROM Product p WHERE p.name LIKE %:keyword%")
List<Product> searchByName(@Param("keyword") String keyword);
}
참고사이트
728x90
'💡 백엔드 > Java' 카테고리의 다른 글
[Java] JPA Specification 이용하여 쿼리 조건 다루기 (2) | 2024.07.23 |
---|---|
소나큐브 7.2.1 버전에서 새로운 프로젝트 등록하기 (1) | 2024.06.28 |
소나큐브 코드스멜 테스트 결과 메시지 분석 (0) | 2024.06.27 |
직렬화(Serialization) 란? (0) | 2024.06.27 |
JAVA의 try-with-resources (0) | 2024.06.25 |