중급 문법

JIWOO YUN·2024년 3월 20일
0

Querydsl

목록 보기
3/7
post-custom-banner

QueryDsl 중급 문법을 들어가기 전에 프로젝션에 대해서 간략하게만 알아보자.


프로젝션

  • JPQL 의 Select 절을 이용하여 어떤 데이터를 조회할 것인가를 말함.
  • Select를 절의 조회 대상을 무엇으로 작성하냐에 따라 프로젝션 종류가 달라진다.
    • Entity 프로젝션
    • Embedded 프로젝션
    • 스칼라 프로젝션

Entity 프로젝션

  • 객체 또는 객체의 속성을 조회하는 Select 문

Embedded 프로젝션

  • Entity의 속성 중 값 타임으로 생성된 속성을 조회하는 Select 문

Scalar 프로젝션

  • 조회하는 데이터의 타입과 상관없이 여러개를 가져오는 방법.

예시

em.createQuery("select p.name, p.age,p.team from player p")
  • 현재 조회하는 세가지 전부 속성이 다름.
  • 전부 다르기 때문에 조회하는 데이터 클래스가 매개변수로 들어가지 않는다.
  • 조회되는 데이터의 자료형을 규정할 수 엇으니 Query 형식 사용

Query 형식 -> 조회 결과의 자료형을 규정할 수없으므로 Object 배열을 사용한다.

참고한 블로그 : 24. JPQL - 프로젝션(Projection, Select) (tistory.com)


프로젝션 결과 반환 - 기본타입

  • 프로젝션 대상이 하나면 타입을 명확하게 지정가능
  • 둘 이상인 경우 튜플이나 DTO로 조회한다.

프로젝션 대상이 하나

List<String> result = queryFactory
        .select(member.username)
        .from(member)
        .fetch();

튜플 조회

  • 둘이상일때 튜플 사용 or DTO 사용
List<Tuple> res = queryFactory
        .select(member.username, member.age)
        .from(member)
        .fetch();

for (Tuple re : res) {
    String username = re.get(member.username);
    Integer age = re.get(member.age);

    System.out.println("username = " + username);
    System.out.println("age = " + age);
}
  • Querydsl 에서 제공하는 tuple

DTO 조회

순수 JPA 에서 DTO를 통해서 조회하는 방법

  • 자주 사용됨으로 잘 알아두자.

순수 JPA 에서 DTO를 조회할 때는 new 명령어를 사용해야한다.

  • new Operation 활용

  • DTO의 package 이름을 다 적어줘야해서 지저분해 보인다.

  • 생성자 방식만 지원.

@Test
public void findDtoByJPQL(){
    List<MemberDto> result = em.createQuery("select new study.querydsl.dto.MemberDto(m.username, m.age)" +
            " from Member m", MemberDto.class).getResultList();
}

QueryDsl 빈생성

  • 결과를 DTO 반환할 때 사용한다.

    • 프로퍼티 접근

      • Setter 기반 동작하기 때문에 MemberDto 객체의 setter를 열어야하는 위험성 존재
        • setter 가열려있는경우 -> 다른 곳에서도 변경이 가능해진다.
      List<MemberDto> result = queryFactory
              .select(Projections.bean(MemberDto.class,
                      member.username,
                      member.age
              ))
              .from(member)
              .fetch();
    • 필드 직접 접근

      • getter,setter 무시하고 필드에 직접 꽂는 방식
            List<MemberDto> result2 = queryFactory
                    .select(Projections.fields(MemberDto.class,
                            member.username,
                            member.age))
                    .from(member)
                    .fetch();
  • 생성자 사용

    • Projections.constructor를 사용
    • 타입을 맞춰야함 -> 맞추면 제대로 불러옴
    queryFactory.select(Projections.constructor(MemberDto.class),
                    member.username,
                    member.age)
            .from(member)
            .fetch();

참고 : Querydsl Projection 방법 소개 및 선호하는 패턴 정리 - Yun Blog | 기술 블로그 (cheese10yun.github.io)

만약 별칭이 다른 경우

.as 를 통해서 별칭 맞춰주기.

@Test
public void diffAlias(){

    QMember memberSub = new QMember("memberSub");
    queryFactory
            .select(Projections.fields(UserDto.class,
                    member.username.as("name"), // userDto의 name 별칭이랑 매칭
                    ExpressionUtils.as(
                            JPAExpressions
                                    .select(memberSub.age.max())
                                    .from(memberSub),"age")
                    )
            ).from(member)
            .fetch();
}
  • 서브 쿼리에 별칭의 경우 ExpressionUtils 를 시용해서 별칭 적용
profile
열심히하자
post-custom-banner

0개의 댓글