select 절에 조회할 대상을 지정하는 것.
그 뭐 sql에서 select 할 때 * 해서 모두 가져오기도 하고, select name, age 해서 뭐 이렇게 2개 가져오기도 하고 그거 말하는 거임.
일단 종류는
엔티티
임베디드 타입
스칼라타입(숫자, 문자 등 기본 데이터)
엔티티는 엔티티 자체, *랑 비슷할 거 같고,
임베디드 타입은 우리가 임베디드 정의한 거 사실 상 테이블에서는 그냥 열 몇개를 객체상에서는 모아놓은 거 이므로,
그냥 테이블에서 그 열들 조회해오는데 자바에서는 그게 그 임베디드 타입 객체로 얻어올 수 있단 이야기같고,
스칼라타입 기본 타입은 그냥 가져오면 됨. name, age 등 숫자나 문자 기본 타입
환경에서 보자면
m -> 엔티티
m,team -> 엔티티
m.address -> 임베디드
m.username, m.age -> 스칼라 타입
참고로 sql과 마찬가지로 앞에 distinct 있으면 중복제거 가능.
참고로, JPQL은 다 영속성 컨텍스트에서 관리가 됨.
Member member = new Member();
member.setUsername("member1");
member.setAge(10);
em.persist(member);
em.flush();
em.clear();
List<Member> result = em.createQuery("select m from Member m", Member.class)
.getResultList();
result.get(0).setAge(30);
tx.commit();
여기 보면 애초에 쿼리를 내보내더라도 em을 써서 내보내기도 하고,
JPA에 의해 관리가 됨.
그리고 join
List<Team> result = em.createQuery("select m.team from Member m", Team.class)
.getResultList();
이렇게 하면 member 테이블에서부터 join해서 가져옴.
Hibernate:
/* select
m.team
from
Member m */ select
t1_0.id,
t1_0.name
from
Member m1_0
join
Team t1_0
on t1_0.id=m1_0.team_id
근데 이거, join되는 거 명시를 해 주셈.
List<Team> result = em.createQuery("select t from Member m join m.team t", Team.class)
.getResultList();
Member로부터 join해온다 Member의 team을 그 team의 별칭을 t 라고 하고 그 t라는 엔티티 프로젝션을 가져온다.
이렇게. 예측할 수 있게.
join 들어가고, 이렇게 sql 나가겠구나 할 수 있게.
그 다음 임베디드 타입
List<Address> result = em.createQuery("select o.address from Order o", Address.class)
.getResultList();
이렇게 할 수 있다.
from에 들어갈 수 있는 건 아무리 그래도 엔티티 밖에 없다.
List resultList = em.createQuery("select m.username, m.age from Member m")
.getResultList();
스칼라 타입.
그럼 이럴 경우 값을 어떻게 돌려주냐?
for (Object o : resultList) {
Object[] result = (Object[]) o;
System.out.println("result = " + result[0]);
System.out.println("result = " + result[1]);
}
좀 불편하긴 한데,
List<Object[]>
각각이 오브젝트 배열로 들어가 있는 느낌.
명시적 형변환도 해줘야 함.
아니면 그냥
List<Object[]> resultList = em.createQuery("select m.username, m.age from Member m", Object[].class)
.getResultList();
for (Object[] o : resultList) {
System.out.println("result = " + o[0]);
System.out.println("result = " + o[1]);
}
애초에 받아올 때 각각을 오브젝트 배열로 받아오면 형변환은 생략 가능.
또 다른 방법은, 깔끔한 방법이기는 한데
List<MemberDTO> resultList = em.createQuery("select new hellojpa.MemberDTO(m.username, m.age) from Member m", MemberDTO.class)
.getResultList();
for (MemberDTO dto : resultList) {
System.out.println("result = " + dto.getUsername());
System.out.println("result = " + dto.getAge());
}
이렇게 DTO를 만들어 new 패키지이름.생성자()
package hellojpa;
public class MemberDTO {
private String username;
private int age;
public MemberDTO(String username, int age) {
this.username = username;
this.age = age;
}
}
이렇게 한다.
저건 특이하게 패키지.생성자() 이렇게 해야 한다.
select new 패키지.생성자(가져올값1, 가져올값2) from 엔티티
말 그대로 new, 새롭게 가져오는 것이다.
많이 씀.
좀 불편한 건 패키지 명을 포함한 전체 클래스명을 입력해야 하지만(문자이기에 한계) 그래도 괜찮음.
'JPA > JPA 기본' 카테고리의 다른 글
41. 조인 (0) | 2023.10.31 |
---|---|
40. 페이징 (0) | 2023.10.31 |
38. JPQL 기본 문법 (0) | 2023.10.30 |
37. JPQL (0) | 2023.10.30 |
36. 값타입 실전 (0) | 2023.10.30 |