[Spring Data JPA] 쿼리 메서드와 페이징
Spring Data JPA 기술을 사용해 회원의 이름과 나이를 기준으로 조회하는 기능을 구현한다고 생각해보자.
공통으로 제공하는 메서드가 아니기 때문에 별도로 처리해 줘야 하는데, 이 때 쿼리 메서드 기능을 사용하면 매우 편하게 처리할 수 있다.
쿼리 메서드를 사용하면 이전처럼 JPQL을 하나하나 작성하지 않아도 된다.
쿼리 메서드는 메서드의 이름을 바탕으로 JPQL을 만들어주는 기술이다.
위와 같이 메서드의 이름을 적절하게 작성하고 매개변수를 설정하면 직관적으로 어떤 JPQL이 만들어지는지 유추할 수 있따.
이 때 아무 이름이나 사용하면 안 되고, 관례가 있다.
이름에 사용되는 관례는 (https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.query-creation) 를 참고하자.
조회는 find ... By
삭제는 delete ... By
위와 같은 형태로 메서드 이름을 작성하는데 find와 By 사이에는 메서드를 설명하는 내용을 포함시킬 수 있다.
작성한 메서드의 반환 타입은 List<Member>, Member 등으로 유연하게 설정할 수 있다.
조회 시 반환 타입이 리스트인데 결과가 없는 경우 비어 있는 컬렉션을 반환하고,
조회 시 반환 타입이 Member (단건 조회) 인데 결과가 없는 경우 null을 반환한다.
단건 조회 시 결과가 2개 이상인 경우 에러를 뱉는다.
엔티티의 필드명이 변경될 경우 메서드에 정의한 이름도 함께 변경해야됨을 잊지 말자.
쿼리 메서드를 사용하면 굉장히 편하게 개발할 수 있지만, 설정하는 조건이 많아지고 전달해야 하는 파라미터들이 많아지는 경우 메서드 이름이 너무 길어지게 된다.
@Query 애너테이션을 사용해 좀 더 간단하게 작성해보자.
실행할 메서드에 @Query 애너테이션을 사용해 정적 쿼리를 작성하고 @Param 애너테이션으로 매개변수를 전달하는 방식으로 동작한다.
@Query 애너테이션에 정의하는 JPQL은 이름 없는 Named Query로 생각할 수 있다.
쿼리에 오타가 있을 때 Named Query를 사용한 경우 애플리케이션 실행 시점에 오타를 찾을 수 있어 실수를 줄일 수 있는데, @Query 애너테이션도 역시 Named Query이기 때문에 실수를 방지할 수 있어 매우 유용하다.
지금은 엔티티를 바로 받아왔는데, DTO나 Primitive Type도 받아올 수 있다.
간단한 경우 쿼리 메서드 방식을 사용하고, 복잡해지는 경우 위와 같이 @Query 애너테이션을 사용하는 편이 합리적이다.
(동적 쿼리는 QueryDsl 기술을 사용하자!!)
Spring Data JPA 기술은 페이징과 정렬 기능을 표준화해서 제공한다.
물론 JPA만 사용해도 페이징과 정렬을 수행할 수 있지만, 페이징 계산도 처리해야 하고, 메서드도 여러 개 사용해야 하고... 그 과정이 좀 귀찮다.
Spring Data JPA는 Sort와 Pageable로 정렬과 페이징을 표준화하고, Page와 Slice는 페이징 결과를 보여줄 때 사용한다.
반환값으로 Page / Slice / List 중 하나를 선택해서 사용하자.
페이지는 0부터 시작함에 주의하자.
PageRequest의 of 메서드를 사용해 어디부터 어디까지 가져올지와 정렬 조건을 설정해 PageRequest 객체를 얻는다.
PageRequest는 인터페이스에 정의한 findByAge 메서드의 인자로 전달되고, 반환값으로 얻은 page를 통해 페이징 관련 대부분의 정보를 획득할 수 있다. (assertThat 참고)
페이징으로 전달되는 쿼리 중 TotalCount 쿼리는 데이터베이스에 있는 모든 데이터를 세는 작업을 거치기 때문에 성능 저하의 원인이 된다.
@Query 애너테이션을 사용해 countQuery를 따로 분리하는 방식으로 문제를 해결할 수 있다.
쿼리가 단순한 경우 Spring Data JPA가 제공하는 페이징을 믿고 맡기고, 복잡한 경우 countQuery를 분리하는 방식을 사용하자.
추가로, 엔티티를 API에 직접 반환하는 방식은 위험하니 꼭 DTO 등으로 변환해서 반환하도록 하자.
위와 같이 map을 통해 Page를 유지하면서 DTO로 변환할 수 있다.
쿼리 메서드로 데이터를 조건에 맞는 데이터를 조회하고 Pageable로 조회된 결과를 페이징한다. 이 부분이 핵심이다.
Spring Data JPA가 제공하는 여러가지 편리한 기능 덕분에 개발자는 핵심 기능에 집중할 수 있게 된다.
'Spring > Spring Data JPA' 카테고리의 다른 글
[Spring Data JPA] 내부 동작 원리 (0) | 2023.01.03 |
---|---|
[Spring Data JPA] 사용자 정의 리포지토리와 확장 기능 (0) | 2023.01.03 |
[Spring Data JPA] 벌크 연산과 EntityGraph (0) | 2023.01.02 |
[Spring Data JPA] 공통 인터페이스 (0) | 2023.01.02 |
댓글
이 글 공유하기
다른 글
-
[Spring Data JPA] 내부 동작 원리
[Spring Data JPA] 내부 동작 원리
2023.01.03 -
[Spring Data JPA] 사용자 정의 리포지토리와 확장 기능
[Spring Data JPA] 사용자 정의 리포지토리와 확장 기능
2023.01.03 -
[Spring Data JPA] 벌크 연산과 EntityGraph
[Spring Data JPA] 벌크 연산과 EntityGraph
2023.01.02 -
[Spring Data JPA] 공통 인터페이스
[Spring Data JPA] 공통 인터페이스
2023.01.02