오봉이와 함께하는 개발 블로그

JPA - 프로젝션(select) 본문

BE/JPA

JPA - 프로젝션(select)

오봉봉이 2022. 6. 30. 00:55
728x90

프로젝션

  • select 절에 조회할 대상을 지정하는 것
  • 프로젝션 대상 : 엔티티, 임베디드 타입, 스칼라 타입(숫자, 문자 등 기본 데이터 타입)
  • SELECT m FROM Member m -> 엔티티 프로젝션
    • 조회하는 대상이 영속성 컨텍스트에 관리된다.
  • SELECT m.team FROM Member m -> 엔티티 프로젝션 (Member의 Team 엔티티 조회)
    • SELECT t FROM Member m join Team t 라고 하는 것이 성능상 더 유리하다.
    • Team을 조회하기 때문에 타입을 Team으로 받아야 하고, 조회도 Team.class로 해야 한다.
  • SELECT m.address FROM Member m -> 임베디드 타입 프로젝션 (Member의 address 임베디드 타입 조회)
    • address를 조회하기 때문에 타입을 Address로 받아야 하고, 조회도 Address.class로 해야 한다.
    • 임베디드 타입은 소속되어 있기 때문에 단독 조회는 불가능하다.
      • selelct a from Address a는 불가능하다.
  • SELECT m.username, m.age FROM Member m -> 스칼라 타입 프로젝션 (Member의 스칼라 타입 조회)
    • 원하는 컬럼만 가져오는 방식
    • 조회는 값의 타입을 특정할 수 없기 때문에(username = String, age = int) 타입은 Query, Object[], new 명령어로 받아야 한다.
    • 조회 클래스(Member.class)도 정할 수 없다.
  • DISTINCT로 중복 제거

프로젝션 - 여러 값 조회

  • SELECT m.username, m.age FROM Member m
    • Query 타입으로 조회
    • Object[] 타입으로 조회
    • new 명령어로 조회
      • 단순 값을 DTO로 바로 조회
        • SELECT new jpabook.jpql.UserDTO(m.username, m.age) FROM Member m
      • 패키지명을 포함한 전체 클래스명 입력
      • 순서와 타입이 일치하는 생성자 필요

Query 타입으로 조회

Query query = em.createQuery("SELECT m.username, m.age, FROM Member m");
List resultList = query.getResultList(); 
Iterator iterator = resultList.iterator();
while (iterator.hasNext()) {    
  Object[] row = (Object[]) iterator.next();    
  String username = (String) row[0];    
  Integer age = (Integer) row[1];
  }

Object[] 타입으로 조회

List resultList = em.createQuery("select m.username, m.age from Member m").getResultList();
Object o = resultList.get(0);
Object[] result = (Object[]) o;

System.out.println("username = " + result[0]);
System.out.println("age = " + result[1]);

// or

List<Object[]> resultList = em.createQuery("select m.username, m.age from Member m").getResultList();
Object[] result = resultList.get(0);

System.out.println("username = " + result[0]);
System.out.println("age = " + result[1]);

new 명령어로 조회

@Getter @Setter
public class MemberDTO {
    private String username;
    private int age;

    // 순서와 타입이 일치하는 생성자 필요
    public MemberDTO(String username, int age) {
        this.username = username;
        this.age = age;
    }
}

// 패키지명을 포함한 전체 클래스명 입력
List<MemberDTO> result = em.createQuery("select new jpql.MemberDTO(m.username, m.age) from Member m", MemberDTO.class)
           .getResultList();
MemberDTO memberDTO = result.get(0);
System.out.println("memberDTO.getUsername() = " + memberDTO.getUsername());
System.out.println("memberDTO.getAge() = " + memberDTO.getAge());

정리

Query 타입이나 Object[] 타입으로 조회하면 굉장히 불편하기 때문에 new 명령어 조회를 사용하자.
단, new 명령어도 패키지가 길어지면 불편할 수 있다.

출처 : 인프런 김영한 지식공유자님의 스프링 부트와 JPA 실무 완전 정복 로드맵 강의
728x90

'BE > JPA' 카테고리의 다른 글

JPA - 조인, 서브 쿼리  (0) 2022.06.30
JPA - 페이징  (0) 2022.06.30
JPA - 기본 문법과 쿼리 API  (0) 2022.06.30
JPA - 객체 지향 쿼리 언어 소개  (0) 2022.06.29
JPA - 실전 예제 6 - 값 타입 매핑  (0) 2022.06.29
Comments