본문 바로가기

JPA

JPQL - Select

JPQL 을 쓸 때, 검색하는 방법을 알아보자.

 

JPQL 은 객체지향적 쿼리기 때문에, 에플리케이션상의 무언가와 매칭되어야 한다.

 

그 무언가의 종류에는 다음과 같은 종류가 있을 수 있다.

  • 엔티티 타입
  • 임베디드 타입
  • 스칼라 타입

 

 

이번 글에서는 다음 엔티티를 사용한다.

@Entity
@Getter
@Setter
public class JPQLMember {

    @Id
    @GeneratedValue
    private Long id;
    private String username;
    private int age;

    @ManyToOne
    @JoinColumn(name = "JPQLTEAM_ID")
    private JPQLTeam team;
}
@Entity
@Getter
public class JPQLOrder {

    @Id
    @GeneratedValue
    private Long id;

    private int orderAmount;

    @Embedded
    private JPQLAddress address;
}

 

 

Entity Selection

select 문을 작성해보자.

 

Member 를 검색하는 JPQL 이다.

TypedQuery<JPQLMember> query = em.createQuery("select m from JPQLMember as m", JPQLMember.class);
List<JPQLTeam> resultList = query1.getResultList();

 

Member의 팀을 검색하는 JPQL 이다.

TypedQuery<JPQLTeam> query1 = em.createQuery("select m.team from JPQLMember as m", JPQLTeam.class);
List<JPQLTeam> resultList = query1.getResultList();

 

연관관계 맵핑된 컬럼의 조회같은 경우 아래와 같이 join 을 사용해서 가져온다.

쿼리문과 실제 날라가는 쿼리가 1:1 매칭되어야 보기 쉽기 때문에 위 방식보다는 join 문을 사용하는 것이 좋다.

    /* select
        m.team 
    from
        JPQLMember as m */ select
            jpqlteam1_.id as id1_14_,
            jpqlteam1_.name as name2_14_ 
        from
            JPQLMember jpqlmember0_ 
        inner join
            JPQLTeam jpqlteam1_ 
                on jpqlmember0_.JPQLTEAM_ID=jpqlteam1_.id

 

 

그리고, getResultList() 의 결과인 List 는 모두 엔티티메니저에 관리되어 영속성 컨텍스트를 가진다.

 

 

 

 

Embedded Selection

JPQLOrder 의 Address 임베디드 타입을 불러올 때에는 select 절에 임베디드 타입을 써주면 된다.

 

TypedQuery<JPQLAddress> query2 = em.createQuery("select o.address from JPQLOrder as o", JPQLAddress.class);
List<JPQLAddress> resultList2 = query2.getResultList();
    /* select
        o.address 
    from
        JPQLOrder as o */ select
            jpqlorder0_.city as col_0_0_,
            jpqlorder0_.street as col_0_1_,
            jpqlorder0_.zipcode as col_0_2_ 
        from
            JPQLOrder jpqlorder0_

 

 

 

 

Scala Selection

일반적으로 DB 에서 컬럼을 지정해서 가져오는 것을 생각하면 쉽다.

하지만 JPA 를 사용하기 때문에, 만약 Member 테이블의 age 와 name 을 가져온다 생각하면 리턴타입은 int 인가, String 인가 ?

 

이를 해결하기 위한 방법들은 아래와 같다.

 

 

1. raw 타입 List로 받아와서 명시적 형변환

List resultList3 = em.createQuery("select m.id, m.age from JPQLMember as m").getResultList();

Object o = resultList3.get(0);
Object[] o1 = (Object[]) o;

System.out.println("id : " + o1[0]);
System.out.println("age : " + o1[1]);

List 안에 배열 형태로 결과를 받아오기 때문에, get() 과 배열의 인덱스를 이용하여 값을 꺼내는 방법.

 

 

 

2. Object[] 타입 List로 받아오기

위의 방법보다 조금 낫지만 여튼 똑같은 방법이다.

List<Object[]> resultList4 = em.createQuery("select m.id, m.age from JPQLMember as m").getResultList();

Object[] o2 = resultList4.get(0);

System.out.println("id : " + o2[0]);
System.out.println("age : " + o2[1]);

 

 

 

 

3. new 명령어 사용

new 명령어로 DTO로 값을 매핑해서 받는다.

 

일단 결과를 받을 DTO 를 만든다.

package jpql;

public class MemberResultDto {

    private Long id;
    private String username;

    public MemberResultDto(Long id, String username) {
        this.id = id;
        this.username = username;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }
}

 

이후 JPQL 은 다음과 같이 작성한다.

List<MemberResultDto> resultList5 = em.createQuery("select new jpql.MemberResultDto(m.id, m.username) from JPQLMember as m", MemberResultDto.class).getResultList();

System.out.println("id : " + resultList5.get(0).getId());
System.out.println("age : " + resultList5.get(0).getUsername());

 

보다시피, Select 문에 new 키워드를 사용하여 생성자를 생성하듯이 해주면 자동으로 DTO 의 리스트를 반환한다.

createQuery() 의 두번째 인자로 DTO 클래스 타입을 준 것도 확인하자.

DTO 의 풀 패키지명(FQCL) 을 적어 준 것도 확인하자.

또, DTO 에는 해당 생성자가 필요하다.

 

결과적으로 다음과 같은 쿼리가 날라가게 된다.

 

    /* select
        new jpql.MemberResultDto(m.id,
        m.username) 
    from
        JPQLMember as m */ select
            jpqlmember0_.id as col_0_0_,
            jpqlmember0_.username as col_1_0_ 
        from
            JPQLMember jpqlmember0_

'JPA' 카테고리의 다른 글

JPQL  (0) 2021.04.22
영속성 컨텍스트를 쓰면 좋은점  (0) 2021.04.14
Entity Manager, 영속성 컨텍스트  (0) 2021.04.13