지나공 : 지식을 나누는 공간

JPA 8 -1 : 프로젝션, 페이징 본문

Tech/JPA

JPA 8 -1 : 프로젝션, 페이징

해리리_ 2020. 12. 13. 17:21

이번에 다룰 내용은,

  • 프로젝션과 영속성컨텍스트 관리여부
  • 여러 필드의 값을 조회하는 방법 세 가지
  • 페이징

 

프로젝션이란?

  • 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
Comments