쿼리 메소드 기능
- 메소드 이름으로 쿼리 생성
- 메소드 이름으로 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가 출력된다.
출처
실전! 스프링 데이터 JPA - 인프런 | 강의
스프링 데이터 JPA는 기존의 한계를 넘어 마치 마법처럼 리포지토리에 구현 클래스 없이 인터페이스만으로 개발을 완료할 수 있습니다. 그리고 반복 개발해온 기본 CRUD 기능도 모두 제공합니다.
www.inflearn.com
'BackEnd > 스프링 데이터 JPA' 카테고리의 다른 글
확장 기능 (0) | 2023.01.23 |
---|---|
@EntityGraph, JPA Hint @ Lock (0) | 2023.01.21 |
벌크성 수정 쿼리 (1) | 2023.01.20 |
JPA 페이징 처리 (0) | 2023.01.14 |
공통 인터페이스 기능 (0) | 2023.01.12 |