Per ardua ad astra !
I'm On My Way
Per ardua ad astra !
전체 방문자
오늘
어제
  • 분류 전체보기 (126)
    • Algorithm (50)
      • 백준 (30)
      • SWEA (3)
      • JUNGOL (3)
      • Programmers (5)
      • LeetCode (2)
    • 안드로이드 개발 (6)
      • Java로 개발 (0)
      • Kotlin으로 개발 (3)
    • Spring (41)
      • Spring기본 (17)
      • JPA기본 (15)
      • JPA활용 SpringBoot 기본 (9)
      • API 개발 기본 (0)
    • 네트워크 (3)
    • 운영체제 (0)
    • Life (3)
      • 책 (0)
      • 자기계발 (1)
      • 일상 (2)
    • 노마드코더 (3)
      • python으로 웹 스크래퍼 만들기 (3)
    • 프로그래밍 언어 (17)
      • Java 기본 (2)
      • 코틀린 기본 (15)

블로그 메뉴

  • 홈
  • 방명록

인기 글

hELLO · Designed By 정상우.
Per ardua ad astra !

I'm On My Way

JPQL를 통한 조회, 페이징
Spring/JPA기본

JPQL를 통한 조회, 페이징

2021. 7. 31. 12:54

프로젝션(조회)

- SELECT 절에 조회할 대상을 지정하는 것

 

프로젝션 대상: 엔티티, 임베디드 타입, 스칼라 타입(숫자, 문자 기본데이터 타입 등)

 

엔티티 타입

 

예시)

엔티티 프로젝션

SELECT m FROM Member m; 
SELECT m.team FROM Member m; 

 

=> team으로 조회할 때 Member에서 Team으로 자동으로 join쿼리를 날려 조회하는 것이다. 이를 알고 명시해주는 작업이 초보자들에겐 필요할 수 있는데, 따라서
"SELECT t from Member m join m.team t"
로 조회하는 것 더 이해하고 학습하기 좋을 것 같다. 

 

 

임베디드 타입

 

예시)

임베디드 프로젝션

SELECT m.address FROM Member m; 

생성한 임베디드 타입 address로 그대로 조회해도 address내의 속성들로 자동 매핑되어 쿼리가 나가고, 조회된다.

 

스칼라 타입

 

예시)

스칼라 프로젝션(숫자, 문자 기본데이터 타입 등)

SELECT m.username, m.age FROM Member m;

distinct가 사용 가능하다.

보통

List<반환타입> resultList = em.createQuery("쿼리문", 반환 타입). getResultList();

위와 같은 코드로 조회를 했었는데, 스칼라 프로젝션은 반환타입이 뚜렷하지 않아서 조회하기 어려움을 겪을 수 있다. 반환타입이 뚜렷하지 않은 경우 조회할 수 있는 방법은 3가지가 있다.

 

조회방법 3가지


1. Query타입으로 조회

=> 불편해서 생략..


2. Object[] 타입으로 조회

 

데이터 삽입

            Member member = new Member();
            member.setAge(20);
            Team team = new Team();
            team.setName("호랑이팀");
            member.setTeam(team);
            member.setUsername("정석우");

            em.persist(team);
            em.persist(member);
            em.flush();
            em.clear();

 

스칼라 타입 조회

List<Object[]> resultList = em.createQuery("select m.username, m.age from Member m").getResultList();
for (Object[] result : resultList) {
        System.out.println("username = " + result[0]);
        System.out.println("age = " + result[1]);
}

1. List의 타입에 Object[]로 설정하고, createQuery의 2번째 파라미터를 비워두어서 타입을 특정짓지 않는다.

2. Object[]에 순서대로 각 스칼라의 값들이 담겨 있다, iter로 추출하여 조회해보자.

  => 주의**: 만약 m.team 등 조인 된 다른 객체를 조회해서 String으로 출력할때, 해당 클래스의 toString() 메소드가 어떻게 구현되어 있느냐에 따라 무한루프가 돌 수 있다. 다른 클래스를 toString()으로 출력할 때는 꼭 무한루프가 도는지 안도는지 확인해서 조회 할 수 있도록 하자 !!



3. new 명령어로 조회


단순 값을 DTO로 바로 조회 가능함 
 -> DTO타입을 만들고, new 라는 키워드를 사용해야함
 

주의: 조회시 패키지명을 포함한 전체 클래스명 입력 필요 ,  순서와 타입이 일치하는 생성자 필요

 

예시)

위의 예제와 똑같이 username과 age를 조회하려한다면, 이 속성들을 포함한 DTO를 생성하면 된다. 특히 주의할 점은 생성자를 조회할 속성 순서에 맞게 만들어놔야 한다.

 

MemberDTO class

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;
    }
}

 

DTO를 통해 스칼라 조회

List<MemberDTO> resultList = em.createQuery("select new jpql.MemberDTO(m.username, m.age) from Member m", MemberDTO.class).getResultList();
for(MemberDTO memberDTO : resultList){
	System.out.println("username = " + memberDTO.getUsername());
	System.out.println("age = " + memberDTO.getAge());
}

1. List타입과, createQuery의 타입을 MemberDTO라는 클래스로 지정할 수 있다.

2. "select new jpql.MemberDTO(m.username, m.age) from Member m"

   ** new라는 키워드를 꼭 사용해야하고 패키지명을 포함한 전체 경로 클래스 명으로 설정해야 한다. **


+JPQL의 프로젝션으로 조회한 모든 데이터들은 영속성 컨텍스트 안에서 관리된다. 

 


페이징 API 

JPA는 페이징을 다음 두 API로 추상화한다.

 

setFirstResult(int startPosition): 조회 시작 위치(0부터 시작)
setMaxResults(int maxResult): 조회할 데이터 수 

 


예시)

            for (int i = 0; i < 100; i++) {
                Member member = new Member();
                member.setAge(i);
                member.setUsername("이름" + i);
                em.persist(member);
            }

            em.flush();
            em.clear();

            List<Member> resultList = em.createQuery("select m from Member m order by m.age desc", Member.class)
                    .setFirstResult(0)
                    .setMaxResults(10)
                    .getResultList();
            for (Member member : resultList) {
                System.out.println("username = " + member.getUsername());
                System.out.println("age = " + member.getAge());
            }

조회 쿼리에서 order by m.age desc로 설정했으므로 age가 높은 순서대로 조회가 될 것이다. 

setFirstResult는 0번째부터(첫번째 값) 

setMaxResults는 10개로 설정했기 때문에 

age가 99인 데이터부터 age가 90인 데이터까지 차례대로 10개가 출력될 것이다. 

 

출력결과

날아간 쿼리

아래에 limit 키워드가 나간 것으로 보아 h2 DB에 맞게 쿼리가 날아간 모습이고

출력도 잘 된 모습이다.

 

 

이 게시물은 '자바 ORM 표준 JPA 프로그래밍' 강의를 수강하고 정리한 내용임을 밝힙니다. 
출처: https://www.inflearn.com/course/ORM-JPA-Basic#

 

자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런 | 강의

JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다., 본 강의는 자바 백엔

www.inflearn.com

    'Spring/JPA기본' 카테고리의 다른 글
    • JPQL 타입과 기타식, CASE 사용 방법, JPQL의 기본함수와 사용자 설정함수
    • JPQL 조인, 서브쿼리
    • 객체지향 쿼리 언어 소개(JPQL, QueryDSL, NativeQuery)
    • Embedded 타입 객체, JPA에서의 값 타입(참조기반) 수정시 주의사항, 값 타입 콜렉션
    Per ardua ad astra !
    Per ardua ad astra !
    개발자 지망생이며 열심히 공부하고 기억하기 위한 블로그입니다.

    티스토리툴바