2023. 9. 29. 00:14ㆍLECTURES/실전! 스프링 데이터 JPA
메소드 이름으로 쿼리 생성
Spring Data JPA - Reference Documentation
Example 121. Using @Transactional at query methods @Transactional(readOnly = true) interface UserRepository extends JpaRepository { List findByLastname(String lastname); @Modifying @Transactional @Query("delete from User u where u.active = false") void del
docs.spring.io
- 조회(SELECT) :
find…By
,query…By
,get…By
- 개수 조회(COUNT) :
count…By
→ long - 존재 여부 조회(EXISTS) :
exists…By
→ boolean - 삭제(DELETE) :
delete…By
,remove…By
- 중복 제거 조회(DISTINCT) :
findDistinct
- 개수 제한(LIMIT) :
findFirst(num)
,findTop(num)
엔티티의 필드명이 변경되면 인터페이스에 정의한 메서드 이름도 꼭 함께 변경해야 함
그렇지 않으면 애플리케이션을 시작하는 시점에 오류 발생
애플리케이션 로딩 시점에 오류를 인지할 수 있는 것이 스프링 데이터 JPA의 큰 장점
JPA NamedQuery
엔티티에 @NamedQuery
애노테이션으로 NamedQuery 정의
@NamedQuery(
name = "Member.findByUsername",
query = "select m from Member m where m.username = :username"
)
public class Member {
...
}
JPA 직접 사용
em.createNamedQuery("Member.findByUsername", Member.class)
.setParameter("username", username)
.getResultList();
스프링 데이터 JPA
@Query(name = "Member.findByUsername")
List<Member> findByUsername(@Param("username") String username);
@Query(name = "Member.findByUsername")
생략 가능- NampedQuery는 정적 쿼리이기 때문에 애플리케이션 실행 시점에 오류를 잡아낼 수 있음
@Query, 리포지토리 메소드에 쿼리 정의하기
@org.springframework.data.jpa.repository.Query
애노테이션 사용- 오타가 있으면 NamedQuery처럼 애플리케이션 실행 시점에 잡아낼 수 있음
- 메소드이름으로 쿼리를 생성할 경우 파라미터가 많아질 수록 메소드명이 길어지므로
@Query
기능을 자주 사용
@Query, 값, DTO 조회하기
파라미터 바인딩
- 위치 기반 :
select m from Member m where m.username = ?0
- 이름 기반 :
select m from Member m where m.username = :name
- 위치 기반은 순서가 바뀌면 다르게 동작할 수 있으니 이름 기반을 쓰는 것이 좋음
- 컬렉션 파라미터 바인딩
- Collection 타입으로 in 절 지원
반환 타입
Spring Data JPA - Reference Documentation
Example 121. Using @Transactional at query methods @Transactional(readOnly = true) interface UserRepository extends JpaRepository { List findByLastname(String lastname); @Modifying @Transactional @Query("delete from User u where u.active = false") void del
docs.spring.io
- 컬렉션
- 단건
- 단건 Optional
- 조회 결과가 없으면
- 컬렉션은 빈 컬렉션 반환
- 단건 조회는 null 반환
- Optional을 사용하는 것이 좋음
- 단건 조회시 결과가 많으면
jakarta.persistence.NonUniqueResultException
발생
순수 JPA 페이징과 정렬
createQuery()
에 offset과 limit 설정setFirstResult(offset)
setMaxResults(limit)
스프링 데이터 JPA 페이징과 정렬
- 페이징과 정렬 파라미터
org.springframework.data.domain.Sort
org.springframework.data.domain.Pageable
- 반환 타입
org.springframework.data.domain.Page
: 추가 count 쿼리 결과를 포함하는 페이징org.springframework.data.domain.Slice
: 추가 count 쿼리 결과 없이 다음 페이지만 확인 가능 → 내부적으로 limit + 1 조회List
: 추가 count 쿼리 없이 결과만 반환
Pageable
인터페이스의 구현 객체인PageRequest
를 사용하여 조회하고자 하는 페이지와 데이터 수, 정렬 정보를 설정- Page는 0부터 시작
left join
을 하는 경우와 같이 조회 쿼리는 복잡하지만 count 쿼리는 간단하게 할 수 있는 경우@Query(value = “select m from Member m, countQuery = “select count(m.username) from Member m”)
와 같이 count 쿼리를 분리할 수 있음- 전체 count 쿼리는 매우 무거움
List<Member> findTop3By()
orList<Member> findFirst3By()
를 사용할 수도 있음페이지를 유지하면서 엔티티를 DTO로 변환
Page<Member> page = memberRepository.findByAge(10, pageRequest);
Page<MemberDto> dtoPage = page.map(m -> new MemberDto());
벌크성 수정 쿼리
@Modifying
애노테이션 사용- 벌크 연산은 영속성 컨텍스트를 무시하고 실행하기 때문에, 영속성 컨텍스트에 있는 엔티티의 상태와 DB의 엔티티 상태가 달라질 수 있음
- 벌크 연산 후
em.clear()
또는@modifying(clearAutomatically = true)
로 영속성 컨텍스트를 초기화한 후 조회해야 함
- 벌크 연산 후
@EntityGraph
지연 로딩을 설정한 경우 N+1 문제가 발생 → fetch join 사용
@Query("select m from Member m left join fetch m.team")
List<Member> findMemberFetchJoin();
@EntityGraph
를 사용하면 페치 조인을 간편하게 사용 가능
//공통 메서드 오버라이드
@Override
@EntityGraph(attributePaths = {"team"})
List<Member> findAll();
//JPQL + 엔티티 그래프
@EntityGraph(attributePaths = {"team"})
@Query("select m from Member m")
List<Member> findMemberEntityGraph();
//메서드 이름으로 쿼리에서 특히 편리하다.
@EntityGraph(attributePaths = {"team"})
List<Member> findByUsername(String username)
@NamedEntityGraph
//Entity
@NamedEntityGraph(name = "Member.all", attributeNodes =
@NamedAttributeNode("team"))
@Entity
public class Member {}
//Repository
@EntityGraph("Member.all")
@Query("select m from Member m")
List<Member> findMemberEntityGraph();
JPA Hint & Lock
- JPA Hint : JPA 구현체에게 제공하는 힌트 → SQL 힌트 X
org.springframework.data.jpa.repository.QueryHints
애노테이션 사용
- Lock
org.springframework.data.jpa.repository.Lock
애노테이션 사용
실전! 스프링 데이터 JPA - 인프런 | 강의
스프링 데이터 JPA는 기존의 한계를 넘어 마치 마법처럼 리포지토리에 구현 클래스 없이 인터페이스만으로 개발을 완료할 수 있습니다. 그리고 반복 개발해온 기본 CRUD 기능도 모두 제공합니다.
www.inflearn.com
'LECTURES > 실전! 스프링 데이터 JPA' 카테고리의 다른 글
나머지 기능들 (0) | 2023.09.29 |
---|---|
스프링 데이터 JPA 분석 (0) | 2023.09.29 |
확장 기능 (0) | 2023.09.29 |
공통 인터페이스 기능 (0) | 2023.09.29 |
프로젝트 환경 설정 / 예제 도메인 모델 (0) | 2023.09.29 |