Query Lookup Strategies

2024. 10. 19. 19:47Spring Boot/Spring Data JPA

쿼리 조회 전략을 설정할 때 queryLookupStrategy 속성에 대한 예시를 추가해보겠습니다. 이 예시에서는 Java 기반 구성에서 각 전략을 어떻게 설정하고 사용하는지를 보여줍니다.

1. CREATE 전략 설정

CREATE 전략은 Spring Data JPA에서 리포지토리 메서드 이름을 기반으로 쿼리를 생성하는 방법을 의미합니다. 이 전략은 메서드 이름에서 특정 접두사를 제거하고 나머지 부분을 분석하여 데이터베이스에 맞는 쿼리를 자동으로 작성합니다.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@Configuration
@EnableJpaRepositories(
    basePackages = "com.example.repository",
    queryLookupStrategy = QueryLookupStrategy.Key.CREATE
)
public class JpaConfig {
}

이제 이 과정을 좀 더 상세히 설명해 보겠습니다.

CREATE 전략의 동작 방식

  1. 메서드 이름 규칙:
    • Spring Data JPA는 메서드 이름에서 쿼리를 생성할 때, 일반적으로 사용되는 몇 가지 접두사를 정의하고 있습니다. 이 접두사들은 쿼리의 목적이나 동작을 나타냅니다. 예를 들어:
      • findBy: 특정 조건에 맞는 엔티티를 찾기 위해 사용
      • countBy: 조건에 맞는 엔티티의 개수를 세기 위해 사용
      • deleteBy: 특정 조건에 맞는 엔티티를 삭제하기 위해 사용
    • 예를 들어, findByLastName이라는 메서드가 있다고 가정해보겠습니다.
  2. 접두사 제거:
    • CREATE 전략은 메서드 이름에서 접두사를 제거하고 나머지 부분을 분석합니다. findByLastName의 경우, findBy 접두사가 제거된 후 LastName이라는 단어만 남게 됩니다.
  3. 쿼리 생성:
    • 남은 단어를 사용하여 쿼리를 생성합니다. 예를 들어, LastName이라는 속성을 가진 User 엔티티에서 해당 속성이 일치하는 모든 레코드를 찾는 쿼리가 생성됩니다. 즉, SQL 쿼리는 다음과 같을 수 있습니다:
      SELECT * FROM user WHERE last_name = ?;
    • 이 쿼리는 last_name 속성이 주어진 값과 일치하는 모든 사용자 레코드를 반환합니다.

예시

아래는 CREATE 전략을 사용하는 몇 가지 메서드 이름 예시입니다:

  • findByFirstName: first_name 속성이 일치하는 모든 레코드를 찾는 쿼리로 변환됩니다.
  • countByAge: age 속성이 일치하는 레코드의 개수를 세는 쿼리로 변환됩니다.
  • deleteByEmail: 특정 email 값을 가진 레코드를 삭제하는 쿼리로 변환됩니다.

 

CREATE 전략은 Spring Data JPA에서 메서드 이름을 기반으로 자동으로 쿼리를 생성하는 방식입니다. 접두사를 제거한 후, 남은 단어들을 분석하여 해당 속성과 매칭되는 쿼리를 작성합니다. 이를 통해 개발자는 복잡한 SQL 쿼리를 직접 작성하지 않고도 데이터베이스 작업을 수행할 수 있게 됩니다.

2. USE_DECLARED_QUERY 전략 설정

USE_DECLARED_QUERY는 선언된 쿼리를 찾으려 하고, 찾을 수 없으면 예외를 throw합니다. 쿼리는 어딘가에 어노테이션으로 정의하거나 다른 방법으로 선언할 수 있습니다.

USE_DECLARED_QUERY 전략은 미리 정의된 쿼리를 사용하도록 설정하는 예시입니다:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.jpa.repository.query.QueryLookupStrategy;

@Configuration
@EnableJpaRepositories(
    basePackages = "com.example.repository",
    queryLookupStrategy = QueryLookupStrategy.Key.USE_DECLARED_QUERY
)
public class JpaConfig {
}

USE_DECLARED_QUERY 전략은 Spring Data JPA에서 미리 정의된 쿼리를 사용하도록 설정하는 방법입니다. 이 전략의 작동 방식과 특징을 자세히 설명하겠습니다.

USE_DECLARED_QUERY의 동작 방식

  1. 미리 정의된 쿼리 찾기:
    • USE_DECLARED_QUERY 전략은 리포지토리 메서드에 대한 미리 정의된 쿼리를 찾습니다. 이러한 쿼리는 주로 메서드에 대한 애너테이션을 통해 정의됩니다. 예를 들어, @Query 애너테이션을 사용하여 쿼리를 정의할 수 있습니다.
  2. 애너테이션 기반 쿼리 정의:
    • 다음은 @Query 애너테이션을 사용하여 쿼리를 정의하는 예시입니다:
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;

public interface UserRepository extends JpaRepository<User, Long> {

    // 1. 특정 나이 이상인 사용자를 찾기 위한 메서드
    @Query("SELECT u FROM User u WHERE u.age >= :age")
    List<User> findUsersByAgeGreaterThanEqual(@Param("age") int age);

    // 2. 특정 성을 가진 사용자 수를 세기 위한 메서드
    @Query("SELECT COUNT(u) FROM User u WHERE u.lastName = :lastName")
    long countByLastName(@Param("lastName") String lastName);

    // 3. 특정 이름을 가진 사용자 중 가장 나이가 많은 사용자를 찾기 위한 메서드
    @Query("SELECT u FROM User u WHERE u.firstName = :firstName ORDER BY u.age DESC")
    User findOldestUserByFirstName(@Param("firstName") String firstName);

    // 4. 이메일로 사용자를 찾되, 이메일 패턴에 따라 여러 사용자를 찾기 위한 메서드
    @Query("SELECT u FROM User u WHERE u.email LIKE %:emailPattern%")
    List<User> findByEmailContaining(@Param("emailPattern") String emailPattern);
}

설명

  1. 특정 나이 이상인 사용자 찾기:
    • findUsersByAgeGreaterThanEqual(int age) 메서드는 입력된 나이 이상인 모든 사용자를 반환합니다.
    • JPQL: SELECT u FROM User u WHERE u.age >= :age
  2. 특정 성을 가진 사용자 수 세기:
    • countByLastName(String lastName) 메서드는 특정 성을 가진 사용자의 수를 반환합니다.
    • JPQL: SELECT COUNT(u) FROM User u WHERE u.lastName = :lastName
  3. 특정 이름을 가진 사용자 중 가장 나이가 많은 사용자 찾기:
    • findOldestUserByFirstName(String firstName) 메서드는 특정 이름을 가진 사용자들을 나이가 많은 순서로 반환합니다.
    • JPQL: SELECT u FROM User u WHERE u.firstName = :firstName ORDER BY u.age DESC
  4. 이메일 패턴으로 사용자 찾기:
    • findByEmailContaining(String emailPattern) 메서드는 주어진 이메일 패턴이 포함된 모든 사용자를 반환합니다.
    • JPQL: SELECT u FROM User u WHERE u.email LIKE %:emailPattern%
  1. 쿼리 미발견 시 예외 발생:
    • USE_DECLARED_QUERY 전략을 사용하는 경우, 리포지토리 인프라가 부트스트랩 단계에서 해당 메서드에 대한 선언된 쿼리를 찾지 못하면 예외를 발생시킵니다. 즉, 쿼리가 없으면 애플리케이션이 정상적으로 실행되지 않고 오류가 발생합니다.
  2. 쿼리 정의 방법:
    • 쿼리는 @Query 애너테이션 외에도 XML 파일이나 다른 설정 파일을 통해 정의될 수 있습니다. 데이터 저장소에 따라 지원되는 쿼리 정의 방법이 다를 수 있으므로, 해당 저장소의 문서를 참조하여 가능한 옵션을 확인해야 합니다.

예외 상황 예시

만약 UserRepository에서 findByEmail 메서드에 대한 쿼리를 정의하지 않았다면, 다음과 같은 상황이 발생할 수 있습니다:

public interface UserRepository extends JpaRepository<User, Long> {

    // @Query 애너테이션이 없으므로 쿼리가 정의되지 않음
    User findByEmail(String email); // 이 메서드는 오류를 발생시킬 수 있음
}

이 경우, findByEmail 메서드는 선언된 쿼리가 없으므로 애플리케이션이 실행될 때 예외가 발생합니다.

 

USE_DECLARED_QUERY 전략은 미리 정의된 쿼리를 찾아서 사용하는 방식입니다. 이 전략을 사용할 때는 리포지토리 메서드에 명시적으로 쿼리를 정의해야 하며, 정의되지 않은 쿼리에 대해서는 예외를 발생시킵니다. 따라서 개발자는 쿼리를 명확히 정의하여 해당 메서드를 사용할 수 있도록 해야 합니다.

3. CREATE_IF_NOT_FOUND 전략 설정 (디폴트값)

CREATE_IF_NOT_FOUND 전략은 기본 전략으로, 선언된 쿼리가 없으면 메서드 이름을 기반으로 쿼리를 생성합니다. 명시적으로 설정하는 예시는 다음과 같습니다:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@Configuration
@EnableJpaRepositories(
    basePackages = "com.example.repository",
    queryLookupStrategy = QueryLookupStrategy.Key.CREATE_IF_NOT_FOUND
)
public class JpaConfig {
}
  • 이 설정에서는 기본 전략인 CREATE_IF_NOT_FOUND를 사용하여, UserRepository 리포지토리에서 다음과 같은 메서드를 정의했다고 가정합니다:
public interface UserRepository extends CrudRepository<User, Long> {

    @Query("SELECT u FROM User u WHERE u.email = :email")
    User findByEmail(@Param("email") String email);

    List<User> findByFirstName(String firstName);
}
  • findByEmail 메서드는 USE_DECLARED_QUERY 전략을 사용하여 미리 정의된 쿼리를 실행하고, findByFirstName 메서드는 CREATE 전략에 따라 메서드 이름을 기반으로 쿼리를 생성합니다.

 

위의 예시를 통해 각 쿼리 조회 전략을 설정하는 방법을 보여주었습니다. ENABLE_JPA_REPOSITORIES 어노테이션의 queryLookupStrategy 속성을 사용하여 설정할 수 있으며, 각 전략의 동작 방식을 이해하는 데 도움이 될 것입니다. 설정한 전략에 따라 리포지토리 메서드는 서로 다른 방식으로 쿼리를 처리하게 됩니다.

'Spring Boot > Spring Data JPA' 카테고리의 다른 글

Reserved Method Names  (1) 2024.10.19
Query Creation  (0) 2024.10.19
Defining Query Methods  (0) 2024.10.19
Persisting Entities  (0) 2024.10.19
Configuration  (3) 2024.10.19