쿼리 메소드 기능
- 메소드 이름으로 쿼리 생성
- 메소드 이름으로 JPA Named Query 호출
- '@Query' 어노테이션을 사용해서 리포지토리 인터페이스에 쿼리 직접 정의
1. 메소드 이름으로 쿼리 생성하는 기능
- docs.spring.io/spring-data/jpa/docs/2.4.2/reference/html/#jpa.query-methods.query-creation
- 간단한 쿼리를 사용할 때 자주 사용한다.
조회 : find...By
COUNT : count...By
EXISTS : exists...By
삭제 : delete...By
DISTINCT : findDistinct
LIMIT : findFirst3, findFirst, findTop
2. JPA NamedQuery
- query 문을 잘못 작성하면, 어플리케이션 로딩 시점이 컴파일 에러를 발생시키는 장점이 있다.
- 엔티티 위에 작성할 수 있다.
@NamedQuery(
name = "Member.findByUsername",
query = "select m from Member m where m.username = :username"
)
public class Member {
JPA 에서 사용하는 방법
public List<Member> findByUsername(String username) {
return em.createNamedQuery("Member.findByUsername", Member.class)
.setParameter("username", username)
.getResultList();
}
Spring Data JPA 에서 사용하는 방법
@Query(name = "Member.findByUsername")
List<Member> findByUsername(@Param("username") String username);
3. @Query, 리포지토리 메소드에 쿼리 직접 정의하기
예시)
@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);
장점
- 간략한 메소드 이름
- 메소드 이름으로 쿼리를 작성하는 기능은 메소드가 너무 길어질 수 있지만, 해당 방법은 메소드 이름은 길어지지 않음
- 어플리케이션 로딩 시점에 컴파일 에러를 제공한다.
4. @Query 로 값, DTO 조회하기
값 조회
@Query("select m.username from Member m")
List<String> findUsernameList();
DTO 조회
- DTO 를 생성한 뒤, 생성자로 객체를 생성하는 것 처럼 하여 사용
@Query("select new study.datajpa.dto.MemberDto(m.id, m.username, t.name) from Member m join m.team t")
List<MemberDto> findMemberDto();
5. 컬렉션 파라미터 바인딩
In 절을 통해서 하는 예제
@Query("select m from Member m where m.username in :names")
List<Member> findbyNames(@Param("names") Collection<String> names);
6. 반환 타입
반환 타입들
- List<T>
- 결과가 없다면 empty List 가 보장됨. (null이 아닌 empty list)
- T
- 결과가 없다면 null 이 반환됨
- Optional<T>
- 결과가 없으면 optional.empty 반환됨
7. 페이징
JPA
- 직접 만든 setFirstResult, setMaxResults 를 이용한 paging query
- 직접 만든 count query
Spring Data JPA
파라미터 | 기능 |
Sort | 정렬조건 |
Pageable | 페이징 기능 (Sort 가 포함되어있다.) PageRequest.of 로 생성 가능 |
결과 값
- Slice
- 내가 파라미터로 준 Pageable 의 limit 보다 한개를 더 요청한다.
- Paging query
- 한개 더 가져와서 다음 페이지가 있음을 알게하도록 (더보기 버튼) 하는 구현을 많이함.
- Page
- Paging Query + Count Query
결과 값 | 사용 가능 함수 | 리턴 값 | 기능 |
Page | getContent() | List<T> | 페이징 조건에 맞는 결과 값 (List<T>) 을 가져온다. |
getTotalElements() | long | count 쿼리에 대한 결과 값을 가져온다. | |
getNumber() | int | 몇번째 페이지인지 반환한다. | |
getTotalPages() | int | 총 페이지수를 반환한다. | |
isFirst() | boolean | 첫번째 페이지인지 알 수 있다. | |
hasNext() | boolean | 다음 페이지가 존재하는지 알 수 있다. | |
Slice | getContent() | List<T> | 페이징 조건에 맞는 결과 값 (List<T>) 을 가져온다. |
getNumber() | int | 몇번째 페이지인지 반환한다. | |
isFirst() | boolean | 첫번째 페이지인지 알 수 있다. | |
hasNext() | boolean | limit 보다 한개 더 요청을 하기 때문에 다음 페이지가 존재하는지 알 수 있다. |
Count Query를 분리할 수 있다.
@Query(value = "select m from Member m left join m.team t",
countQuery = "select count(m) from Member m")
Page<Member> findByAge(int age, Pageable pageable);
DTO 로 변환하여 api에서 리턴하자
Page<Member> page = memberRepository.findByAge(age, pageRequest);
Page<MemberDto> toMap = page.map(member -> new MemberDto(member.getId(), member.getUsername(), null));
8. 벌크성 수정 쿼리
Spring Data JPA
- @Modifying(clearAutomatically = true)
- 반환값은 int
@Modifying
@Query("update Member m set m.age = m.age + 1 where m.age >= :age")
int bulkAgePlus(@Param("age") int age);
9. @EntityGraph
Spring Data Jpa 에서는 fetch join 을 편리하게 할 수 있다.
ex) fetch join
@Query("select m from Member m left join fetch m.team")
List<Member> findMemberFetchJoin();
ex) @EntityGraph
@EntityGraph(attributePaths = {"team"})
List<Member> findAll();
@EntityGraph(attributePaths = {"team"})
List<Member> findEntityGraphByUsername(@Param("username") String username);
10. JPA Hint & Lock
1. ReadOnly 기능
- 100% 조회용으로만 사용할 것이다.
- dirty checking 최적화
@QueryHints(value = @QueryHint(name = "org.hibernate.readOnly", value = "true"))
Member findReadOnlyByUsername(String username);
2. Lock
- DB에 Lock 을 걸 수 있다.
ex) 쿼리문에 select for update (lock 을 거는 select 가 추가되는 모습)
@Lock(LockModeType.PESSIMISTIC_WRITE)
List<Member> findLockByUsername(String username);
// 쿼리문
select
member0_.member_id as member_i1_0_,
member0_.age as age2_0_,
member0_.team_id as team_id4_0_,
member0_.username as username3_0_
from
member member0_
where
member0_.username=? for update
'강의 정리 > 스프링 데이터 JPA' 카테고리의 다른 글
3. 확장 기능 (0) | 2021.01.14 |
---|---|
1. extends JpaRepository (0) | 2021.01.10 |