728x90
반응형
JPQL 프로젝션은 SELECT 절에 조회할 대상을 지정하는 것을 의미한다.
프로젝션 대상에는 엔티티, 임베디드 타입, 스칼라 타입(숫자, 문자 등 기본 데이터 타입) 이 해당된다.
엔티티 프로젝션에는 쿼리로 표현하면
SELECT m FROM Member m
SELECT m.team FROM Member m
이 있고,
이를 코드로 표현하면
List<Member> result = em.createQuery("select m from Member m", Member.class).getResultList();
List<Team> result = em.createQuery("select m.team from Member m join m.team t", Team.class).getResultList();
와 같이 표현할 수 있다.
임베디드 타입 프로젝션은 쿼리로 표현하면
SELECT m.address FROM Member m
이 있고,
이를 코드로 표현하면
List<Address> addresses = em.createQuery("select o.address from Order o", Address.class).getResultList();
와 같이 된다.
스칼라 타입 프로젝션은 쿼리롤 표현하면
SELECT m.username, m.age FROM Member m
처럼 표현할 수 있고,
이를 코드로 표현하면
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("username = " + result[0]);
System.out.println("age = " + result[1]);
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]);
와 같이 쓸 수 있다.
위처럼 "DISTINCT" 를 붙이면 중복을 없앨 수 있다.
※ 프로젝션으로 여러 값을 조회할 땐
SELECT m.username, m.age FROM Member m
를 예로 들면
(1) Query 타입으로 조회할 수 있다. → 반환 타입이 명확하지 않을 때 이처럼 사용할 수 있다.
Query query = em.createQuery("SELECT m.username, m.age from Member m");
(2) 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
- 패키지 명을 포함한 전체 클래스 명을 입력한다
- 순서와 타입이 일치하는 생성자가 필요하다.
MemberDTO.java
package jpql;
public class MemberDTO {
private String username;
private int age;
public MemberDTO(String username, int age) {
this.username = username;
this.age = age;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
JpaMain.java
package jpql;
import javax.persistence.*;
import java.util.List;
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try{
Member member = new Member();
member.setUsername("member1");
member.setAge(10);
em.persist(member);
List<MemberDTO> resultList = em.createQuery("select new jpql.MemberDTO(m.username, m.age) from Member m", MemberDTO.class).getResultList();
MemberDTO memberDTO = resultList.get(0);
System.out.println("memberDTO.getUsername() = " + memberDTO.getUsername());
System.out.println("memberDTO.getAge() = " + memberDTO.getAge());
tx.commit();
} catch (Exception e) {
tx.rollback();
e.printStackTrace();
} finally {
em.close();
}
// code
emf.close();
}
}
728x90
반응형
'자바 > JPA' 카테고리의 다른 글
[JPA/Java] JPQL 조인(Join) (0) | 2023.05.09 |
---|---|
[JPA/Java] 페이징 API (0) | 2023.05.03 |
[JPA/Java] JPQL 기본 문법과 기능 (0) | 2023.04.27 |
[JPA/Java] 객체지향 쿼리 언어 종류 (0) | 2023.04.27 |
[JPA/Java] For property-based access both setter and getter should be present 문제 해결 @Access or @Column (0) | 2023.03.13 |
댓글