지나공 : 지식을 나누는 공간
JPA 8 -1 : 프로젝션, 페이징 본문
이번에 다룰 내용은,
- 프로젝션과 영속성컨텍스트 관리여부
- 여러 필드의 값을 조회하는 방법 세 가지
- 페이징
프로젝션이란?
- 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로 중복 제거
영속성 컨텍스트에 관리되는가?
em.flush(); //DB에
em.clear(); //영속성컨텍스트 비움
List<Member> result = em.createQuery("select m from Member m", Member.class)
.getResultList();
Member findMember = result.get(0);
findMember.setAge(20);
영속성 컨텍스트를 비운 뒤에 프로젝션을 하면 조회된 것들이 영속성 컨텍스트에 올라가서 관리된다.
em.clear()를 통해 영속성컨텍스트를 비웠지만 프로젝션을 실행하면 영속성 컨텍스트에서 관리된다.
m.team을 조회하면 List<Team>으로 받게 될 것이고 이것이 영속성 컨텍스트에 올라갈 것이다.
임베디드 타입을 가져오는 쿼리라면 아래와 같다.
List<Address> address = em.createQuery("select o.Address from Order o", Address.class)
.getResultList();
여러 값(필드) 조회하기
1. Query 타입으로 조회하기
TypeQuery는 반환 타입이 명확할 때, Query는 반환 타입이 명확하지 않을 때 사용한다.
Query처럼 타입이 명확하지 않을 때 아래와 같이 코드를 작성할 수 있다.
List resultList = em.createQuery("select m.username, m.age from Member m")
.getResultList(); //타입을 모르는 Query타입
Object o = result.get(0);
Object[] result = (Object[]) o;
System.out.println("username = " + result[0]);
System.out.println("age = " + result[1]);
타입 명시를 못하므로 Obejct 배열을 활용한 타입 캐스팅이 필요하다.
2. Object[] 타입으로 조회하기
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]);
3. new 명령어로 조회하기
필요한 여러 값을 가진 DTO 생성 후 조회
@Getter
public class MemberDTO{
private String username;
private int age;
}
쿼리에 패키지명을 써야한다. 패키지명이 길어지면 조금 곤란해지긴 하지만.
//DTO 자체를 조회할 땐 그냥 m이라고 표현 가능
List<MemberDTO> resultList = em.createQuery("select m from Member m", MemberDTO.class)
.getResultList();
//m.username, m.age만 조회하고 싶을 땐 패키지명을 다 써야 한다.
List<MemberDto> resultList = em.createQuery("select new jpql.MemberDTO(m.username, m.age) from Member m", MemberDTO.class)
.getResultList();
MemberDTO memberDTO = result.get(0);
System.out.println("memberDTO = " + memberDTO.getUsername());
System.out.println("memberDTO = " + memberDTO.getAge());
- 패키지명을 포함한 전체 클래스 명을 입력해야 한다.
- 순서와 타입이 일치하는 생성자가 필요하다.
페이징 API - JPA는 페이징을 다음 두 API로 추상화
- setFirstResult(int startPosition) : 조회 시작 위치 (0부터 시작)
- setMaxResult(int maxResult) : 조회할 데이터의 수
List<Member> result = em.createQuery("select m from Member m order by m.age desc", Member.class)
.setFirstResult(0)
.setMaxResult(10);
.getResultList();
System.out.println("result.size = " + result.size());
728x90
'Tech > JPA' 카테고리의 다른 글
JPA 8 -3 : JPQL 타입 표현과 기타식, JPQL 기본 함수 (0) | 2020.12.20 |
---|---|
JPA 8 -2 : 조인, ON절, 서브쿼리, JPA 서브쿼리 한계 (0) | 2020.12.14 |
JPA 8 : JPQL 기본 문법과 쿼리 API (0) | 2020.12.09 |
JPA 7-2 : 값 타입 컬렉션 (0) | 2020.12.07 |
JPA 7-1 : 값 타입과 불변 객체, 값 타입 비교 (2) | 2020.11.10 |
Comments