Query DSL - 정렬, 페이징, 집합

2022. 8. 6. 20:44·공부/JPA
반응형

출처 : 인프런 실전! QueryDSL

Query DSL게시글은 대부분 인프런의 김영한님의 강의인 '실전! Query DSL' 기반으로 내용을 정리했습니다.

 

정렬

정렬 기준은 다음과 같다.

  • 회원 나이 내림차순(desc)
  • 회원 이름 오름차순(asc)
    • 단, 회원 이름이 없으면 마지막에 출력한다.
@Test
public void sort() {
    em.persist(new Member(null, 100));
    em.persist(new Member("member5", 100));
    em.persist(new Member("member6", 100));

    List<Member> result = queryFactory
            .selectFrom(member)
            .where(member.age.eq(100))
            .orderBy(member.age.desc(), member.username.asc().nullsLast())
            .fetch();

    Member member5 = result.get(0);
    Member member6 = result.get(1);
    Member memberNull = result.get(2);
    assertThat(member5.getUsername()).isEqualTo("member5");
    assertThat(member6.getUsername()).isEqualTo("member6");
    assertThat(memberNull.getUsername()).isNull();
}

 

/* select
    member1 
from
    Member member1 
where
    member1.age = ?1 
order by
    member1.age desc,
    member1.username asc nulls last */ select
        member0_.member_id as member_i1_1_,
        member0_.age as age2_1_,
        member0_.team_id as team_id4_1_,
        member0_.username as username3_1_ 
    from
        member member0_ 
    where
        member0_.age=? 
    order by
        member0_.age desc,
        member0_.username asc nulls last

참고로 nullsLast() 말고 nullsFirst()도 존재한다. nullsFirst()를 사용할 경우 회원 이름에 null 값이 존재하는 회원이 제일 위로 정렬된다. nullsFirst로 변경하면 검증은 아래와 같다.

Member memberNull = result.get(0);
Member member5 = result.get(1);
Member member6 = result.get(2);

assertThat(memberNull.getUsername()).isNull();
assertThat(member5.getUsername()).isEqualTo("member5");
assertThat(member6.getUsername()).isEqualTo("member6");

 


페이징

@Test
public void paging1() {
    List<Member> result = queryFactory
            .selectFrom(member)
            .orderBy(member.username.desc())
            .offset(1) // 0부터 시작
            .limit(2)
            .fetch();

    assertThat(result.size()).isEqualTo(2);
}
/* select
    member1 
from
    Member member1 
order by
    member1.username desc */ select
        member0_.member_id as member_i1_1_,
        member0_.age as age2_1_,
        member0_.team_id as team_id4_1_,
        member0_.username as username3_1_ 
    from
        member member0_ 
    order by
        member0_.username desc limit ? offset ?

 

전체 조회 수가 필요할 경우

@Test
public void paging2() {
    QueryResults<Member> queryResults = queryFactory
            .selectFrom(member)
            .orderBy(member.username.desc())
            .offset(1) // 0부터 시작
            .limit(2)
            .fetchResults();

    assertThat(queryResults.getTotal()).isEqualTo(4);
    assertThat(queryResults.getLimit()).isEqualTo(2);
    assertThat(queryResults.getOffset()).isEqualTo(1);
    assertThat(queryResults.getResults().size()).isEqualTo(2);
}
// count query
/* select
    count(member1) 
from
    Member member1 */ select
        count(member0_.member_id) as col_0_0_ 
    from
        member member0_


// paging query
/* select
    member1 
from
    Member member1 
order by
    member1.username desc */ select
        member0_.member_id as member_i1_1_,
        member0_.age as age2_1_,
        member0_.team_id as team_id4_1_,
        member0_.username as username3_1_ 
    from
        member member0_ 
    order by
        member0_.username desc limit ? offset ?

참고로 count 쿼리가 따로 실행되는 만큼 성능을 주의해야 한다. 페이징 쿼리를 작성할 때 복잡한 조인이 일어나는 경우, count 쿼리는 조인이 필요 없을 수도 있다. 이런 상황에서 fetchResults()로 count 쿼리까지 가져오면 count 쿼리마저 조인이 일어나 성능이 저하되므로 이런 경우에는 분리해서 따로 작성하는 게 맞다.

 


집합

@Test
public void aggregation() {
    List<Tuple> result = queryFactory
            .select(member.count(),
                    member.age.sum(),
                    member.age.avg(),
                    member.age.max(),
                    member.age.min())
            .from(member)
            .fetch();

    Tuple tuple = result.get(0);
    assertThat(tuple.get(member.count())).isEqualTo(4);
    assertThat(tuple.get(member.age.sum())).isEqualTo(100);
    assertThat(tuple.get(member.age.avg())).isEqualTo(25);
    assertThat(tuple.get(member.age.max())).isEqualTo(40);
    assertThat(tuple.get(member.age.min())).isEqualTo(10);
}

Tuple은 QueryDSL에서 제공하는 타입이다. 여러 타입을 반환 받을 때 주로 사용하며 더 자세한 내용은 추후에 설명한다.

집합 함수는 JPQL이 제공하는 모든 집합 함수를 사용할 수 있다.

 

GroupBy

각 팀별 회원 나이의 평균을 구해보자.

@Test
public void group() throws Exception {
    List<Tuple> result = queryFactory
            .select(team.name, member.age.avg())
            .from(member)
            .join(member.team, team) // 나중에 설명!
            .groupBy(team.name) // team의 이름으로 grouping
            .fetch();

    Tuple teamA = result.get(0);
    Tuple teamB = result.get(1);

    assertThat(teamA.get(team.name)).isEqualTo("teamA");
    assertThat(teamA.get(member.age.avg())).isEqualTo(15);


    assertThat(teamB.get(team.name)).isEqualTo("teamB");
    assertThat(teamB.get(member.age.avg())).isEqualTo(35);
}

.having()도 groupBy 체인에 이어서 사용할 수 있다.

 

반응형
저작자표시 비영리 변경금지 (새창열림)
'공부/JPA' 카테고리의 다른 글
  • Query DSL - 결과 조회
  • Query DSL - 검색 조건 쿼리
  • QueryDSL - 기본 Q-Type 활용
  • Query DSL - JPQL vs QueryDSL
데부한
데부한
어차피 할 거면 긍정적으로 하고 싶은 개발자
    반응형
  • 데부한
    동동이개발바닥
    데부한
  • 전체
    오늘
    어제
    • 분류 전체보기 (307)
      • 방통대 컴퓨터과학과 (27)
        • 잡담 (9)
        • 3학년1학기 (17)
      • 프로젝트 및 컨퍼런스 회고 (1)
        • 프로젝트 (4)
        • 한이음 프로젝트 (0)
        • 회고 (3)
      • 공부 (165)
        • Spring (37)
        • JPA (71)
        • 인프런 워밍업 클럽_BE (10)
        • Java (6)
        • React.js (27)
        • 넥사크로 (11)
        • 기타 (3)
      • 알고리즘 (85)
        • 알고리즘 유형 (10)
        • 알고리즘 풀이 (57)
        • SQL 풀이 (18)
      • 에러 해결 (13)
      • 잡담 (7)
        • 국비교육 (2)
        • 구매후기 (5)
        • 진짜 잡담 (0)
  • 블로그 메뉴

    • Github
    • Linkedin
    • 홈
    • 방명록
    • 글쓰기
    • 관리
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    QueryDSL
    에러해결
    프로그래머스
    코딩테스트
    egov
    Java
    넥사크로
    react
    Spring
    백준
    방통대
    토비의스프링부트
    oracle
    스프링부트
    운영체제
    토이프로젝트
    자바스크립트
    SpringBoot를 이용한 RESTful Web Service 개발
    JPA
    개발자
    springboot
    알고리즘
    RESTful
    SQL
    전자정부프레임워크
    기출문제
    프론트엔드
    IT
    인프런
    MSA
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
데부한
Query DSL - 정렬, 페이징, 집합
상단으로

티스토리툴바