[Spring Data JPA] - Query method 기능 ②

홍정완·2022년 7월 11일
0

JPA

목록 보기
17/38
post-thumbnail

@Query - Repository 메서드에 쿼리 정의하기


// 메서드에 JPQL 쿼리 작성

public interface MemberRepository extends JpaRepository<Member, Long> {

@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);

}

  • @org.springframework.data.jpa.repository.Query 어노테이션 사용

  • 실행할 메서드에 정적 쿼리를 직접 작성하므로 이름 없는 Named 쿼리라 할 수 있음


  • JPA Named 쿼리처럼 애플리케이션 실행 시점에 문법 오류를 발견할 수 있음

    • 매우 큰 장점

  • 메서드 이름으로 쿼리 생성 기능은 파라미터가 증가하면, 메서드 이름이 매우 지저분

    • 따라서 @Query 기능을 자주 사용



@Query - 값, DTO 조회하기


// 단순히 값 하나를 조회

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

  • JPA 값 타입 @Embedded도 이 방식으로 조회 가능



// 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로 직접 조회하려면 JPA의 new 명령어를 사용해야 한다.

  • 그리고 다음과 같이 생성자가 맞는 DTO가 필요

    • JPA와 사용 방식이 동일

import lombok.Data;

@Data
public class MemberDto {
 	private Long id;
 	private String username;
 	private String teamName;
 
 
 	public MemberDto(Long id, String username, String teamName) {
 		this.id = id;
 		this.username = username;
 		this.teamName = teamName;
 	}
    
}



파라미터 바인딩


select m from Member m where m.username = ?0 	// 위치 기반
select m from Member m where m.username = :name // 이름 기반

  • 코드 가독성과 유지 보수를 위해 이름 기반 파라미터 바인딩을 사용하자

// 파라미터 바인딩

import org.springframework.data.repository.query.Param

public interface MemberRepository extends JpaRepository<Member, Long> {

	@Query("select m from Member m where m.username = :name")
	Member findMembers(@Param("name") String username);
}



// 컬렉션 파라미터 바인딩

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

  • Collection 타입으로 in 절 지원



반환 타입



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



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


  • 컬렉션
    • 결과 없음 : 빈 컬렉션 반환

  • 단건 조회
    • 결과 없음 : null 반환
    • 결과가 2건 이상 : javax.persistence.NonUniqueResultException 예외 발생



단건으로 지정한 메서드를 호출하면, 스프링 데이터 JPA는 내부에서 JPQL Query.getSingleResult() 메서드 호출

  • 이 메서드를 호출했을 때 조회 결과가 없으면javax.persistence.NoResultException 예외 발생

  • 개발자 입장에서 다루기가 상당히 불편

  • 스프링 데이터 JPA는 단건을 조회할 때 이 예외가 발생하면 예외를 무시하고 대신에 null
    반환
profile
습관이 전부다.

0개의 댓글