@Query

최종윤·2023년 1월 6일

JPA

목록 보기
11/15

https://www.petrikainulainen.net/programming/spring-framework/spring-data-jpa-tutorial-creating-database-queries-with-the-query-annotation/

method name strategy로 생성한 db query를 @Query로 구현해보자.

Query Methods 생성

@Query는 JPQL과 SQL queries를 둘다 지원합니다.
@Query를 붙여 생성하는 db query는 다른 모든 생성 전략보다 우선합니다.
``
interface TodoRepository extends Repository<Todo, Long> {

@Query("SELECT t FROM Todo t WHERE t.title = 'title'")
public List<Todo> findById();

}
``
해당 query method는 @Query가 붙어있으므로, method name strategy로 생성하는 query를 무시하고, @Query 로 생성한 query를 호출합니다.

JPQL 과 SQL 생성하는 법

JPQL Queries 생성법

  1. repo interface에 query method를 추가합니다.
  2. query method에 @Query를 붙이고 ,@Query에 호출되는 query를 value로 지정합니다.

SQL Queries 생성법

  1. repo interface에 query method를 추가합니다.
  2. @Query를 붙이고, 호출되는 query를 @Query의 value로 지정합니다.
  3. @Query의 nativeQuery 속성 값을 true로 지정합니다.
    ``
    interface TodoRepository extends Repository<Todo, Long> {
    @Query(value = "SELECT * FROM todos t WHERE t.title = 'title'",
            nativeQuery=true
    )
    public List<Todo> findByTitle();
    }
    ``

Search Function 구현

case 구별하지 않고, description or title이 term을 포함하는 entries를 반환하는 query를 생성하는 Function을 구현해봅시다.

JPQL로 Search Function 구현

@Query("select t from todo t where t.title like %:term% or t.description like %:term%")
List<todo.> findByTerm(@Param("term") String term);

named parameter의 name을 지정한 @Param을 method parameter에 붙인다.
contains 와 ignoreCase를 구현하기 위해 다음과 같이 query를 생성한다.
``
interface TodoRepository extends Repository<Todo, Long> {

@Query("SELECT t FROM Todo t WHERE " +
        "LOWER(t.title) LIKE LOWER(CONCAT('%',:searchTerm, '%')) OR " +
        "LOWER(t.description) LIKE LOWER(CONCAT('%',:searchTerm, '%'))")
List<Todo> findBySearchTerm(@Param("searchTerm") String searchTerm);

}
``
ignore case는 db에 있는 값을 Lower로 다 소문자로 바꾼다.

SQL로 구현

``
interface TodoRepository extends Repository<Todo, Long> {

@Query(value = "SELECT * FROM todos t WHERE " +
        "LOWER(t.title) LIKE LOWER(CONCAT('%',:searchTerm, '%')) OR " +
        "LOWER(t.description) LIKE LOWER(CONCAT('%',:searchTerm, '%'))",
        nativeQuery = true
)
List<Todo> findBySearchTermNative(@Param("searchTerm") String searchTerm);

}
``

nativeQuery = true로 지정하고, JPQL대신 SQL로 작성하여 @Query의 value로 넣어준다.

SQL String function

CONCAT()은 합쳐진 String을 return
LOWER()은 argumetn의 lowercase를 return

언제 @Query?

장점
JPQL과 SQL을 지원합니다.
호출되는 query가 무엇인지 query method위에서 알 수 있습니다.
SQL을 알면 naming convention을 몰라도 구현할 수 있습니다.

단점
동적 쿼리를 지원하지 않습니다.
sQL queries를 사용할때, SQL queries가 기대한대로 동작하는지 테스트하지 않고서는 사용되는 db를 바꿀 수 없습니다.

method name strategy 보다 읽거나 쓰기 어렵지만 중요한 장점을 가집니다.
1. query method위에 invoked query를 볼 수 있습니다.
2. method name이 길지 않아 query method를 사용하는 code의 가독성이 좋습니다.

요약

profile
https://github.com/jyzayu

0개의 댓글