JPA JPQL 프로젝션(Projection)(+DTO)

KMS·2022년 4월 12일
0

JPA Basics

목록 보기
13/20

JPQL 간단 소개 & 문법

테이블이 아닌 객체를 대상으로 검색하는 객체 지향 쿼리
한마디로 정의하면 객체 지향 SQL
JPQL은 엔티티 객체를 대상으로 쿼리하며, SQL로 변환해서 DB를 접근해줍니다.


1. 엔티티와 속성은 대소문자를 구분합니다.(ex: Member != member 엔티티, Member.age != Member.AGE)
2. JPQL 키워드는 대소문자를 구분하지 않습니다. (ex: SELECT == select, FROM == from, WHERE == where ...)
3. 별칭은 필수입니다. (ex: select m from Member m || select m from Member as m)
as는 생략 가능합니다.

프로젝션

기본

List<Member> resultList = em.createQuery("select m from Member m", Member.class)
                    .getResultList();

엔티티의 모든 값들을 가져올때 사용하는 방식입니다. 하지만, 엔티티에서 특정 속성들만 가져오고 싶을때는 어떻게 하면 될까요?

방법 1. new DTO로 값 조회하기 (가장 선호되는 방법)

MemberDTO

public class MemberDTO {
    private Long id;
    private String username;
    private int age;
    private MemberType memberType; //Member에서 memberType을 MemberType으로 지정했으므로, MebmerDTO에서도 MemberTpye으로 지정해줘야 됨

    public MemberDTO() {
    }

    public MemberDTO(String username, int age) {
        this.username = username;
        this.age = age;
    }

    public MemberDTO(Long id, String username, int age) {
        this.id = id;
        this.username = username;
        this.age = age;
    }

    public MemberDTO(Long id, MemberType memberType) {
        this.id = id;
        this.memberType = memberType;
    }

    public MemberDTO(Long id, int age, MemberType memberType) {
        this.id = id;
        this.age = age;
        this.memberType = memberType;
    }

    public Long getId() {
        return id;
    }

    public String getUsername() {
        return username;
    }

    public int getAge() {
        return age;
    }

    public MemberType getMemberType() {
        return memberType;
    }

    public void setMemberType(MemberType memberType) {
        this.memberType = memberType;
    }
}
			// MemberDTO(username, age) 생성자 호출
            List<MemberDTO> resultList = em.createQuery("select new jpql.MemberDTO(m.username, m.age) from Member m", MemberDTO.class)
                    .getResultList();
            for (MemberDTO dto : resultList) {
                System.out.println("dto.getUsername() = " + dto.getUsername());
                System.out.println("dto.getAge() = " + dto.getAge());
            }
            /**
             * dtoId.getUsername() = member1
             * dtoId.getAge() = 25
             */

            //MemberDTO(id, username, age) 생성자 호출
            List<MemberDTO> resultListId = em.createQuery("select new jpql.MemberDTO(m.id, m.username, m.age) from Member m", MemberDTO.class)
                    .getResultList();

            for (MemberDTO dtoId : resultListId) {
                System.out.println("dtoId.getId() = " + dtoId.getId());
                System.out.println("dtoId.getUsername() = " + dtoId.getUsername());
                System.out.println("dtoId.getAge() = " + dtoId.getAge());
            }
            /**
             * dtoId.getId() = 1
             * dtoId.getUsername() = member1
             * dtoId.getAge() = 25
             */

만약에 Member 엔티티에서 id, username, age를 가져오고 싶을때, MemberDTO(id, username, age) 생성자를 호출해서 해당 속성들만 가져오도록 합니다.
이때, MemberDTO의 변수들은 Member의 속성들과 이름과 타입이 같도록 해줍니다.

방법 2. Query타입으로 조회하기

			List resultList1 = em.createQuery("select m.username, m.age from Member m")
                    .getResultList();
            for (Object o : resultList1) {
                Object[] oo = (Object[]) o;
                //index 1 => m.username, index 2 => m.age
                System.out.println("oo.getUsername() = "+ oo[0]);
                System.out.println("oo.getAge() = "+ oo[1]);
            }

방법 3. Object[] 타입으로 조회하기

            List<Object[]> resultList2 = em.createQuery("select m.username, m.age from Member m")
                    .getResultList();
            for (Object[] result : resultList2) {
                //index 1 => m.username, index 2 => m.age
                System.out.println("result.getUsername() = " + result[0]);
                System.out.println("result.getAge() = " + result[1]);
            }```
profile
Student at Sejong University Department of Software

0개의 댓글