-
프로젝션(SELECT)JPA/JPQL 2023. 7. 13. 23:07
프로젝션이란?
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를 넣어서 중복 제거 가능 ("select distince m.username, m.age from Member m"처럼)
간단한 것이지만 중요한 내용이 있다.
엔티티 프로젝션을 하면 그 엔티티의 대상이 영속성 컨텍스트로 관리된다는 것이다. 그래서 변경을 하더라도 db에 업데이트 쿼리가 자동으로 들어간다.
여러 값 조회
- SELECT m.username, m.age FROM Member m -> 스칼라 타입 프로젝션
위와 같은 상황에서 타입이 2개인데 어떻게 조회해야 하는지에 대한 정리이다.
첫 번째 방법
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]);
위와 같이 List에 Object의 배열을 넘겨준 다음에 출력을 해보면 username과 age의 값이 둘 다 출력된다.
두 번째 방법(가장 추천)
MemberDto를 별도로 만들어서 Dto를 반환하게 해주는 것이다.
MemberDto.class
public class MemberDto { private String username; private int age; public MemberDto(String username, int age) { this.username = username; this.age = age; } }
실제 동작
List<Object[]> resultList = em.createQuery("select new jpql.MemberDto(m.username, m.age) from Member m", MemberDto.class) .getResultList(); // 쿼리문에 jqpl.MemberDto에서 jqpl은 인텔리제이의 패키지명 Object[] result = resultList.get(0); System.out.println("username = " + memberDto.getUsername()); System.out.println("age = " + memberDto.getAge());
주의할 점은 createQuery안에 m.username과 m.age를 사용할 때 jpql.MemberDto(m.username, m.age)라고 명시해줘야 한다는 것이다. (jpql.MemberDto는 패키지와 클래스 경로)
-> 이건 QueryDSL에서 해결 가능하다고 한다.
'JPA > JPQL' 카테고리의 다른 글
경로 표현식 (0) 2023.08.09 조건식 (CASE) (0) 2023.07.14 서브 쿼리 (0) 2023.07.14 페이징, 조인 (0) 2023.07.14 JPA에서의 쿼리 언어들 (0) 2023.07.13