Skip to main content

JPQL-중급

·338 words·2 mins· loading
Table of Contents
JPA - This article is part of a series.
Part 11: This Article

경로 표현식
#

.으로 객체 그래프를 탐색

SELECT	 m.username  -> 상태필드
	FROM Member m
    	join m.team t -> 단일  연관 필드
        join m.orders o -> 컬렉션  연관 필드
    where t.name = 'TEAM_A'
  • 상태 필드 : 단순히 값을 저장하기 위한 필드 -> 경로 탐색의 끝이므로 탐색 ❌
  • 연관 필드 : 연관관계를 위한 필드 -> 묵시적 내부 조인 발생
  • 단일값 : @ManyToOne, @OneToOne, 엔티티(m.team) -> 탐색 ⭕️
  • 컬렉션 : @OneToMany, 대상이 컬렉션 (m.orders) -> 탐색 ❌

실무에선 묵시적 내부조인이 최대한 발생하지 않는 쪽으로 하자 => 무조건 명시적 조인 사용


fetch join ❗️❗️❗️
#

JPQL에서 성능 최적화를 위해 제공하는 기능 join fetch

  • 연관된 엔티티나 컬렉션을 SQL 한 번에 같이 조회하는 기능 (즉시 로딩)
  • FetchType.LAZY 보다 우선됨

Distinct
#

DB에서는 join에 여러 결과가 있으면, 다중 row를 반환한다.

String query = "select t From Team t join fetch t.members  ";
	List<Team> resultList = em.createQuery(query, Team.class)
								.getResultList();

따라서, resultList에는 중복된 team이 들어가게 된다.

Distinct를 사용해서, 엔티티의 중복을 제거할 수 있다.

  • String query = "select distinct t From Team t join fetch t.members ";

한계
#

  • 폐치 조인 대상에는 별칭 사용 ❌(권장)
  • 둘 이상의 컬렉션엔 사용❌
  • 컬렉션 패치 조인시, 페이징API 사용 ❌

지금은 쓸 일이 없겠지만, 나중에 이 이걸 읽을때, hibernate.default_batch_fetch_size에 대해 알아보자


엔티티 직접 사용시
#

String query = "select m From Member m where m.team = :team "; 이런식으로 엔티티를 직접 사용시엔 엔티티 ID값을 사용함

String query = "select m From Member m where m.team.id = :teamid "; 여기에 teamid를 직접넘기는것도 같은 SQL 생성


Named쿼리
#

@NamedQuery를 사용해서 미리 이름을 부여해두고 사용하는 JPQL ( ** 정적쿼리만 가능 **)

  • 애플리케이션 로딩 시점에 초기화(검증) 후 재사용)
@Entity
@NamedQuery(
        name = "Member.findByUsername",
        query = "select m from Member m  where m.username = :username"
)
public class Member {
///////////////////////
//main
List<Member> resultList = em.createNamedQuery("Member.findByUsername", Member.class)
                    .setParameter("username", "user1")
                    .getResultList();

스프링 데이터 JPA서는 repository에 코딩 가능


벌크 연산
#

한방에 여러개 업데이트

     int resultCount = em.createQuery("update Member m set m.age = 20 where 1=1 ")
                    .executeUpdate(); // 업데이트   반환

영속성 컨텍스트를 무시하고 DB에 쿼리가 들어가기 때문에, 벌크연산을 먼저 실행하고 -> 영속성 컨텍스트 초기화 em.claer()

JPA - This article is part of a series.
Part 11: This Article