![[Spring] 쿼리 메서드 기능 이해 및 응용1](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlzvBR%2FbtsiWRKYfaf%2FL3UqZEvCmoBC5k8tDKqOi0%2Fimg.png)
JpaRepository를 상속받은 repository는 save(), findAll(), findById() 메서드를 따로 구현하지 않아도 사용 가능합니다. 그렇다면 findByName처럼 이름으로 조회를 하고 싶을 때는 어떻게 해야 할까요?
Query Method?
JPA Query Method는 메서드 이름을 사용하여 데이터베이스에서 데이터를 검색하기 위해 Spring Data JPA Repository에서 쿼리를 정의하는 방법입니다. 쿼리 메서드의 기능은 다음과 같습니다.
- 메서드 이름으로 쿼리 생성
- 메서드 이름으로 JPA NamedQuery 호출
- @Query 어노테이션을 사용해 repository interface에 쿼리 직접 정의
메서드 이름으로 쿼리 생성
DB에 영희, 철수, 명규가 저장되어 있고, 영희라는 이름으로 조회를 하여 영희의 정보를 가져오는 예시입니다.
조회 시 사용하는 문법은 "find + (엔티티 이름) + By + 변수 이름"을 사용합니다.
@Entity @Getter
@RequiredArgsConstructor
@AllArgsConstructor
public class Member {
@Id @GeneratedValue
private Long id;
private String name;
private String phoneNumber;
public Member(String name, String phoneNumber) {
this.name = name;
this.phoneNumber = phoneNumber;
}
}
@Repository
public interface MemberRepository extends JpaRepository<Member, Long> {
//이름으로 조회
Optional<Member> findByName(String name);
//이름과 전화번호로 조회
List<Member> findByNameAndPhoneNumber(String name, String phoneNumber);
}
스프링 데이터 JPA는 findByName 메서드의 이름을 분석하여 JPQL을 생성하고 실행합니다.
쿼리 메서드 필터 조건은 JPA 공식 문서에서 참고 가능합니다.
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/
@Test
public void findByNameTest(){
Member member1 = new Member("영희", "010-1111-1111");
Member member2 = new Member("철수", "010-2222-2222");
Member member3 = new Member("명규", "010-3333-3333");
memberRepository.save(member1);
memberRepository.save(member2);
memberRepository.save(member3);
Optional<Member> findMember = memberRepository.findByName("영희");
Assertions.assertThat(findMember.get().getName()).isEqualTo("영희");
Assertions.assertThat(findMember.get().getPhoneNumber()).isEqualTo("010-1111-1111");
}
테스트가 잘 되는 것을 확인할 수 있습니다.
주의!
엔티티의 필드명이 변경되면 인터페이스에 정의한 메서드 이름도 함께 변경해야 합니다.
@Query 어노테이션 사용하기
필터 조건에 Name과 PhoneNumber뿐만 아니라, Age, Gender 등 많은 필드가 들어가면, 메서드 이름을 findByNameAndPhoneNumberAndAgeAndGender와 같이 작성해야 하므로 메서드 이름이 매우 지저분해집니다.
이 경우, @Query 어노테이션을 사용하면 깔끔하게 해결이 가능합니다.
멤버 테이블은 위의 예시와 같습니다.
@Repository
public interface MemberRepository extends JpaRepository<Member, Long> {
@Query("select m from Member m where m.name = :name and m.phoneNumber = :phoneNumber")
List<Member> findMember(@Param("name") String name, @Param("phoneNumber") String phoneNumber);
}
@Query 어노테이션에 실행할 메서드의 쿼리를 작성하면 메서드 이름이 findByNameAndPhoneNumber보다 간결하게 작성이 가능합니다.
@Test
public void findByNameTest(){
Member member1 = new Member("영희", "010-1111-1111");
Member member2 = new Member("철수", "010-2222-2222");
Member member3 = new Member("명규", "010-3333-3333");
memberRepository.save(member1);
memberRepository.save(member2);
memberRepository.save(member3);
List<Member> findMember = memberRepository.findMember("영희", "010-1111-1111");
Assertions.assertThat(findMember.size()).isEqualTo(1);
Assertions.assertThat(findMember.get(0)).isEqualTo(member1);
}
추가적인 기능은 다음에 더 다루겠습니다!
'Spring' 카테고리의 다른 글
[Spring] Swagger 사용하기 (0) | 2023.06.14 |
---|---|
[Spring] 엔티티에 생성일자 및 수정일자 칼럼 간편히 추가하기 (0) | 2023.06.12 |
[Spring]OSIV와 성능 최적화 (0) | 2023.06.06 |
[Spring] OneToMany 관계에서 페치 조인 최적화 (0) | 2023.05.03 |
[Spring] spring.datasource.driver-class-name 에러 (0) | 2023.04.25 |
느리더라도 단단하게 성장하고자 합니다!
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!