프로젝션(SELECT)

프로젝션

  • SELECT 절에 조회할 대상을 지정하는 것

  • 프로젝션 대상: 엔티티, 임베디드 타입, 스칼라 타입(숫자, 문자등 기본 데이터 타입)

  • SELECT m FROM Member m -> 엔티티 프로젝션

  • SELECT m.team FROM Member m -> 엔티티 프로젝션

  • SELECT m.address FROM Member m -> 임베디드 타입 프로젝션

  • SELECT m.username, m.age FROM Member m -> 스칼라 타입 프로젝션

  • DISTINCT로 중복 제거

엔티티 타입으로 조회하는 경우 엔티티를 반환한다. 이 반환된 엔티티는 영속성 컨텍스트 관리 대상일까? 엔티티 컬렉션을 반환한다면 그 엔티티 하나하나 다 영속성 컨텍스트 관리된다.

조인

  • 묵시적 조인

  • 명시적 조인(권장)

묵시적 조인

List<Team> teamResult = em.createQuery("select m.team from Member m", Team.class).getResultList();

join연산은 성능에 영향을 주는 튜닝할 요소들이 많기 때문에 JPQL에서 m.team을 조회할 때에 join연산이 일어나는데 최대한 SQL과 유사하게 작성해야한다.

Member와 Team을 조인해서 조인한 Team의 엘리엇을 t로 가져온다.(SQL이 예측되도록)

List<Team> teamResult = em.createQuery("select t from Member m join m.team t", Team.class).getResultList();

Address 값 타입만 조회👇🏻

em.createQuery("select o.address from Order o", Address.class).getResultList();

스칼라 타입 값 2개 조회

em.createQuery("select distinct m.username, m.age from Member m").getResultList();

프로젝션 - 여러 값 조회 SELECT m.username, m.age FROM Member m

  1. Query로 조회 : 값이 여러개이므로 값을 특정하지 못하기 때문 타입을 알지 못할 때(타입을 명시해주지 않으면) 리턴타입은 Query가 된다. 이렇게 반환된 query에는 object가 들어가있다.

Query query = em.createQuery("select m.username,m.age from Member m");

2. Object[ ]로 형변환(캐스팅)해서 조회. .getResultList()를 리스트 타입으로 반환한다. resultList의 첫번째 객체Object[ ]로 형변환한다! Object의 0번째, 1번째 값들이 각각 username과 age에 해당한다!

List resultList = em.createQuery("select distinct m.username, m.age from Member m").getResultList();//현재 타입이 없음.
Object o = resultList.get(0);//Object배열이 들어가있을 것이다!
Object[] result = (Object[]) o;
System.out.println("username = " + result[0]);
System.out.println("age = " + result[1]);

위의 코드에서 리턴되는 List의 제네릭을 Object[ ]로 하면 자동 캐스팅된다.

List<Object[]> resultList = em.createQuery("select distinct 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]);

3. new 명령어로 조회 => 마치 별칭 자리에 생성자를 호출하듯이!

  • 단순 값을 DTO로 바로 조회
 SELECT new jpabook.jpql.UserDTO(m.username, m.age) FROM

    Member m

  • 패키지명을포함한전체클래스명입력 (한계점) =>QueryDSL을 이용해서 Java코드로 짜면 import해서 사용할 수 있다.

  • 순서와 타입이 일치하는 생성자 필요

List<MemberDTO> result = em.createQuery("select distinct new jpql.MemberDTO(m.username, m.age) from Member m", MemberDTO.class)
        .getResultList();//현재 타입이 없음.

MemberDTO memberDTO = result.get(0);
System.out.println("memberDTO.username = " + memberDTO.getUsername());
System.out.println("memberDTO.age = " + memberDTO.getAge());

용어 정리 SELECT (*) FROM Member m (*) :엘리아스(별칭)

Last updated