ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Querydsl - 정렬과 페이징, 집합
    JPA/Querydsl 2023. 8. 12. 23:28

    정렬

    /**
    * 회원 정렬 순서
    * 1. 회원 나이 내림차순(desc)
    * 2. 회원 이름 올림차순(asc)
    * 만약, 회원 이름이 없으면 마지막에 출력(nulls last)
    */
    @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())
                // nullsLast는 해당 데이터가 null이면 마지막으로 정렬 (nullsFirst는 맨 앞으로)
                .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();
    }

    기본 데이터들의 나이는 적기 때문에 테스트를 위해 새로 persist한 데이터들이 조건에 의해서 먼저 나오게 될 것이다. 나이가 많은 순으로 정렬하고 이름 순으로 올림차순 했으니 member5가 첫 번째, member6가 두 번째이다. memberNull은 이름이 없다. 하지만 member.username.asc().nullsLast라는 문장에 의해 나이로 정렬로 한 뒤, 이름의 정렬을 할 때 맨 뒤로 가기때문에 나이가 같은 member5, member6 바로 아래에서 조회가 되는 것이다.

     

     

     

    desc(), asc()로 기본 정렬

    nullsLast(), nullsFirst()로 null 값 정렬

     

     

     

     

    페이징

    @Test
    public void paging1() {
        List<Member> result = queryFactory
                .selectFrom(member)
                .orderBy(member.username.desc())
                .offset(0)
                .limit(2)
                .fetch();
    
        assertThat(result.size()).isEqualTo(2);
    }
    
    @Test
    public void paging2() { // 전체 조회수까지 필요할 때
        QueryResults<Member> result = queryFactory
                .selectFrom(member)
                .orderBy(member.username.desc())
                .offset(0)
                .limit(2)
                .fetchResults();
    
        assertThat(result.getTotal()).isEqualTo(4);
        assertThat(result.getLimit()).isEqualTo(2);
        assertThat(result.getOffset()).isEqualTo(0);
        assertThat(result.getResults().size()).isEqualTo(2);
    }

    전체 조회 개수가 필요하면 paging2()처럼 fetchResults()로 결과를 조회하면 된다.

    하지만 성능 상 전체 조회 개수를 분리해야 한다면 paging1()처럼 fetch()를 사용하면 된다.

     

     

     

     

    집합

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

    count(), sum() 등의 집합을 사용하는데 JPQL과 방법이 매우 유사해서 별도의 설명 없이 이해할 수 있을 것이다.

     

     

     

    @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)
                .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);
    }

    groupBy를 team.name으로 해오는 것이다. 반환 타입이 Tuple의 리스트로 반환되는 특징이 있다.

     

     

    Querydsl을 공부하고 있는데 기본적으로 JPQL과 많이 겹치는데 JPQL을 간편하게 해주는 것이라 이해하기 어렵진 않지만 JPQL을 더 확실하게 공부하고 Querydsl도 실수 없이 사용할 수 있도록 익숙해져야 한다는 생각이 들었다.

    'JPA > Querydsl' 카테고리의 다른 글

    Querydsl - 서브 쿼리  (0) 2023.08.13
    Querydsl - 조인  (0) 2023.08.13
    Querydsl - 검색(select)과 결과 조회  (0) 2023.08.12
    Querydls과 JPQL의 차이  (0) 2023.08.12
    Querydls의 기본 설정  (0) 2023.08.12
Designed by Tistory.