프로젝션이란 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 // 스칼라 타입 프로젝션

엔티티 프로젝션은 엔티티 전체를 조회하는 것이다.

임베디드 타입은 임베디드 타입으로 된 값을 조회하는 것인데, 임베디드 타입은 다른 엔티티에 소속되어 있기 때문에 당연히 From절에서 나오지 않는다.

스칼라 타입은 위의 코드와 같이 원하는 값만 뽑아오는 것을 말한다.

스칼라 타입 프로젝션 - 여러 값 조회

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

Member 엔티티의 username과 age를 각각 뽑아오기 위해서는 크게 3가지 방법이 있다.

1. Query Type

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

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

리스트를 받아오는데 어떤 타입인지 명시하지 않고 쿼리 타입으로 받아오는 방법이다. 엔티티나 타입을 지정하지 않았기 때문에 Object로 받아서 거기서 다시 Object배열로 뽑아와야한다.

비효율적.

2. Object[] Type

List<Object[]> resultList2 = em.createQuery("select distinct m.username, m.age from Member m").getResultList();

System.out.println("result[0] = " + resultList2.get(0)[0]);
System.out.println("result[0] = " + resultList2.get(0)[1]);

위의 방법에서 조금 간소화한 방법이다.

3. new 명령어로 조회

List<MemberDTO> resultList1 = em.createQuery("select  new jpql.MemberDTO(m.username, m.age) from Member m", 	 
                              MemberDTO.class)
                              .getResultList();

MemberDTO memberDTO = resultList1.get(0);

System.out.println("memberDTO.toString() = " + memberDTO.toString());

DTO를 따로 만들어서 불러올 수 있다. 근데 String이라 해당 DTO의 경로명을 모두 적어야한다. 또한 DTO클래스의 순서와 타입이 일치하는 생성자가 필요하다.