BackEnd/스프링 데이터 JPA

쿼리 메소드 기능

인프라 감자 2023. 1. 14. 15:50

쿼리 메소드 기능

  • 메소드 이름으로 쿼리 생성
  • 메소드 이름으로 JPA NamedQuery 호출
  • @Query 어노테이션을 사용해서 리파지토리 인터페이스에 쿼리 직접 정의

 

메소드 이름으로 쿼리 생성

List<Member> findByUsernameAndAgeGreaterThan(String username, int age);

Spring Data Jpa가 메소드 이름만으로 원하는 것을 구현해준다. 이름과 나이를  가지고 age 보다 큰 이름들을 알고 싶다면 위 코드처럼 findByUsername (username으로 찾을거에요), And, AgeGreaterThan(int age) 이런 식으로 생각해 원하는 값을 출력해준다.

 

스프링 데이터 JPA가 제공하는 쿼리 메소드 기능

  • 조회: find…By ,read…By ,query…By get…By 
  • COUNT: count…By 반환타입 long
  • EXISTS: exists…By 반환타입 boolean
  • 삭제: delete…By, remove…By 반환타입 long
  • DISTINCT: findDistinct, findMemberDistinctBy
  • LIMIT: findFirst3, findFirst, findTop, findTop3 

 

JPA  NamedQuery

JPA의 NamedQuery를 호출할 수 있다.(거의 실무에서 쓸일이 없다고 하신다)

  • Member 엔티티 추가
@NamedQuery(
        name = "Member.findByUsername",
        query = "select m from Member m where m.username = :username"
)
  • Named 쿼리 호출
public List<Member> findByUsername(String username) {
    return em.createNamedQuery("Member.findByUsername", Member.class)
            .setParameter("username", "회원1")
            .getResultList();
}

위에서 만든 NamedQuery로 메소드를 만들 수 있다.

  • 인터페이스에 한방에 구현 가능
@Query(name = "Member.findByUsername")
List<Member> findByUsername(@Param("username") String username);

더 신기한건 Query를 생략해도 메서드 이름만으로 Named 쿼리를 호출할 수 있다. 어떻게 호출하면 JpaRepository<Member, Long> 일경우 Member에 메소드이름이 findByUsername이므로 Member.findByUsername을 찾는다.

 

@Query, 리포지토리 메소드에 쿼리 정의하기

  • MemberRepository (interface)
@Query("select m from Member m where m.username = :username and m.age =: age")
List<Member> findUser(@Param("username") String username, @Param("age") int age);
  • 인터페이스에 바로 위 코드처럼 쿼리를 집어 넣을 수 있다.
  • @Query는 이름이 없는 NamedQuery라 생각하면 된다.
  • JPA Named 쿼리처럼 애플리케이션 실행 시점에 문법 오류를 발견할 수 있다(매우 큰 장점!)

 

@Query, 값, DTO 조회하기

단순히 값 하나를 조회

@Query("select m.username from Member m")
List<String> findUsernameList();

 

DTO로 직접 조회

@Query("select new study.datajpa.dto.MemberDto(m.id, m.username, t.name) from Member m join m.team t")
List<MemberDto> findMemberDto();
  • DTO를 직접 만들어서 출력한다.
  • DTO로 직접 조회 하려면 JPA의 new 명령어를 사용해야 한다. 그리고 다음과 같이 생성자가 맞는 DTO가 필요하다. (JPA와 사용방식이 동일하다.)

 

파라미터 바인딩

  • 위치 기반 : select m from Member m where m.username = ?0
  • 이름 기반 : select m from Member m where m.username = :name -> 이름 기반을 많이 사용함

 

컬렉션 파라미터 바인딩

@Query("select m from Member m where m.username in :names")
List<Member> findByNames(@Param("names") List<String> names);

m.username in :names 가 List를 파라미터로 받아온다.

 

반환 타입

List<Member> findByUsername(String name); //컬렉션
Member findByUsername(String name); //단건
Optional<Member> findByUsername(String name); //단건 Optional

스프링 데이터 JPA는 유연한 반환 타입을 지원한다.

 

조회 결과가 많거나 없으면? 

  • 컬렉션 : 결과 없으면 빈 컬렉션을 반환한다.
  • 단건 조회 : 결과 없으면 NULL을 반환하고 결과가 2건 이상이면 javax.persistence.NonUniqueResultException 예외 발생시킨다.
  • Optional로 지정하면  데이터가 있든지 없든지간에 에러를 띄우지않는다. Optional.empty가 출력된다. 

 

출처

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%8D%B0%EC%9D%B4%ED%84%B0-JPA-%EC%8B%A4%EC%A0%84/dashboard

 

실전! 스프링 데이터 JPA - 인프런 | 강의

스프링 데이터 JPA는 기존의 한계를 넘어 마치 마법처럼 리포지토리에 구현 클래스 없이 인터페이스만으로 개발을 완료할 수 있습니다. 그리고 반복 개발해온 기본 CRUD 기능도 모두 제공합니다.

www.inflearn.com