쿼리 메소드 기능

2023. 9. 29. 00:14LECTURES/실전! 스프링 데이터 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() or List<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