Query Methods

최종윤·2023년 1월 6일

JPA

목록 보기
9/15

https://www.petrikainulainen.net/programming/spring-framework/spring-data-jpa-tutorial-introduction-to-query-methods/

기본 CRUD 동작을 지원하는 Repository를 생성하는 것만으로 실제 앱을 구현하기 어렵다. custom한 검색 기준을 써서 db query를 할 수 있어야한다.

Query methods란

Query methods를 사용하여 custom db queries를 생성할 수 있다.
Todo Object를 특정 Id값을 갖는 객체를 조회하는 query를 생성하고 싶다면
TodoRepository<>에 findById() 라는 query method를 추가한다.

Query methods의 return value

하나의 값, 혹은 하나 이상(리스트) 를 반환할 수 있다.
비동기적으로 호출되는 query method를 생성할 수도 있다.
상황에 따라 다른 반환 값을 반환하도록 할 수 있다.

하나의 값을 반환하는 경우

Basic type 으로 지정하면 basic type or null 반환
Entity 으로 지정하면 entity의 type or null 반환
Optional<> - 해당 객체를 담는 Optional 혹은 empty Optional 객체를 반환

특정 컬럼을 조회할 때는 basic type or Optional<>을 반환하네
전체 entity 컬럼을 조회할 때는 entity type or Optional을 하겠네
예제)
``
interface TodoRepository extends Repository<Todo, Long> {

@Query("SELECT t.title FROM Todo t where t.id = :id") 
String findTitleById(@Param("id") Long id);
 
@Query("SELECT t.title FROM Todo t where t.id = :id") 
Optional<String> findTitleById(@Param("id") Long id);

Todo findById(Long id);
 
Optional<Todo> findById(Long id);

}
``

리스트를 반환하는 경우

List<> - query method가 query 결과들을 포함하는 List 혹은 empty List를 반환한다.
Stream<> - query method가 query 결과들을 access하는데 쓰이는 Stream 혹은 empty Stream을 반환한다.

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

List<Todo> findByTitle(String title);
 
Stream<Todo> findByTitle(String title);

}
``

비동기적으로 query method 실행

@Async를 붙이고 2. 반환 값을 Future<> 로 지정한다.

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

@Async
@Query("SELECT t.title FROM Todo t where t.id = :id") 
Future<String> findTitleById(@Param("id") Long id);
 
@Async
@Query("SELECT t.title FROM Todo t where t.id = :id") 
Future<Optional<String>> findTitleById(@Param("id") Long id);

@Async
Future<Todo> findById(Long id);
 
@Async
Future<Optional<Todo>> findById(Long id);

@Async
Future<List<Todo>> findByTitle(String title);
 
@Async
Future<Stream<Todo>> findByTitle(String title);

}
``

Query methods에 parameters 전달 방법

position based parameter binding

method parameter의 순서가 어느 placeholders가 parameters로 대체될지 결정한다.
1번째 method parameter가 1번째 placeholder를 대체하고,
2번째 method parameter가 2번째 placeholder를 대체한다.

position based parameter binding 예제
``
interface TodoRepository extends Repository<Todo, Long> {

public Optional<Todo> findByTitleAndDescription(String title, String description);
 
@Query("SELECT t FROM Todo t where t.title = ?1 AND t.description = ?2")
public Optional<Todo> findByTitleAndDescription(String title, String description);
 
@Query(value = "SELECT * FROM todos t where t.title = ?0 AND t.description = ?1", 
    nativeQuery=true
)
public Optional<Todo> findByTitleAndDescription(String title, String description);

}
``
이 방식은 조금 실수를 하기 쉽다.
db query를 breaking하지 않고서는
method parameters의 순서 또는 placeholders의 순서를 바꿀수 없기 떄문이다.

named parameter

전 방식의 numeric placeholders를 db query의 parameter의 이름으로 대체한다.
method parameters에 각각 @Param 을 붙인다.
method parameter 값으로 대체될 parameter의 name을 지정한다.

@Param

query method에 parameter를 (@Param("id") Long id) 이렇게 지정한다.
@Param에 query method에 전달될 parameter의 이름을 지정하고,
값 전달받을 method parameter를 지정한다.

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

@Query("SELECT t FROM Todo t where t.title = :title AND t.description = :description")
public Optional<Todo> findByTitleAndDescription(@Param("title") String title, 
                                                @Param("description") String description);
 
@Query(
    value = "SELECT * FROM todos t where t.title = :title AND t.description = :description", 
    nativeQuery=true
)
public Optional<Todo> findByTitleAndDescription(@Param("title") String title, 
                                                @Param("description") String description);

}

``

요약

  • 기본 Crud 동작으로는 앱 구현에 어려움이 있으므로 custom dq queries를 생성할 수 있어야 한다.
  • custom dq queries를 생성하기 위해 repo interface에 query method를 추가한다.
  • DATA JPA repositories는 다양한 값을 반환할 수 있어 직접 구현하지 않고 사용할 수 있다. basic, entity, Optioanl, List, Stream를 반환한다.
  • @Async를 query method에 붙여 비동기적으로 실행하는 db queries를 생성할 수 있다.
  • query method 생성 방식은 position based parameter binding,
    named parameter 방식이 있는데
  • position based parameter binding는 parameter 순서 바꿀수 없어 실수가 쉬워 named parameter 방식을 사용하면 그런 문제를 해소한다.
profile
https://github.com/jyzayu

0개의 댓글