Programming/Querydsl(KYH)

Querydsl - 기본 문법 (2) (결과 조회, 정렬, 페이징, 집합)

잇(IT) 2023. 7. 27. 13:04
- 결과 조회

1. fetch() : 리스트 조회, 데이터 없으면 빈 리스트 반환

2. fetchOne() : 단 건 조회

 2.1. 결과가 없으면 : null

 2.2. 결과가 둘 이상이면 : NonUniqueResultException 예외 발생

3. fetchFirst() : limit(1).fetchOne()

4. fetchResults() : 페이징 정보 포함, total count 쿼리 추가 실행

5. fetchCount() : count 쿼리로 변경해서 count 수 조회

@Test
    public void resultFetch() {
//        List<Member> fetch = queryFactory
//                .selectFrom(member)
//                .fetch();
//
//        Member fetchOne = queryFactory
//                .selectFrom(member)
//                .fetchOne();
//
//        Member fetchFirst = queryFactory
//                .selectFrom(member)
//                .fetchFirst();

QueryResults<Member> results = queryFactory
.selectFrom(member)
.fetchResults();

        //쿼리를 하나 작성했는데 쿼리가 2번 나갈 것이다.
        //1. getTotal() 메서드를 가져오기 위해선 Count 쿼리가 나가야 하기 때문이다. -> 페이징을 위한 것이다. (1번, 2번 페이지)
        //2. content용 쿼리를 한 번 더 나간다.

results.getTotal();
List<Member> content = results.getResults(); //getResults()로 데이터를 가져올 수 있다.

//        long total = queryFactory
//                .selectFrom(member)
//                .fetchCount();
    }

 

QueryResults<Member> results = queryFactory
.selectFrom(member)
.fetchResults();

        //쿼리를 하나 작성했는데 쿼리가 2번 나갈 것이다.
        //1. getTotal() 메서드를 가져오기 위해선 Count 쿼리가 나가야 하기 때문이다. -> 페이징을 위한 것이다. (1번, 2번 페이지)
        //2. content용 쿼리를 한 번 더 나간다.

results.getTotal();
List<Member> content = results.getResults(); //getResults()로 데이터를 가져올 수 있다.

- fetchResults()는 페이징 정보를 포함하기 때문에, select 이외에 Count 쿼리를 추가로 보낸다.

long total = queryFactory
.selectFrom(member)
.fetchCount();

- fetchCount는 count 쿼리만 날린다.


- 정렬
/*
    * 회원 정렬 순서
    * 1. 회원 나이 내림차순 (desc)
    * 2. 회원 이름 오름차순 (asc)
    * 단, 2에서 회원 이름이 없으면 마지막에 출력 (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())
                .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();
    }

- 회원 정렬 순서

 1. 회원 나이 내림차순 (desc)

 2. 회원 이름 오름차순 (asc)

 단, 2에서 회원 이름이 없으면 마지막에 출력 (nulls last)

- desc() , asc() : 일반 정렬

- nullsLast() , nullsFirst() : null 데이터 순서 부여


- 페이징    

 

- 조회 건수 제한

@Test
    public void paging() {
        List<Member> result = queryFactory
                .selectFrom(member)
                .orderBy(member.username.desc())
                .offset(1)
                .limit(2)
                .fetch();

        assertThat(result.size()).isEqualTo(2);
    }

- 페이징은 쿼리에 직접 페이징 쿼리를 넣는게 아니라 밖에서 넣어주는 것이기 때문에 쿼리에 페이징 관련 쿼리는 없고 결과를 보면 limit, offset을 확인 할 수 있다.

 

- 전체 조회

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

        assertThat(queryResults.getTotal()).isEqualTo(4);
        assertThat(queryResults.getLimit()).isEqualTo(2);
        assertThat(queryResults.getOffset()).isEqualTo(1);
        assertThat(queryResults.getResults().size()).isEqualTo(2);
    }

 assertThat(queryResults.getTotal()).isEqualTo(4);
        assertThat(queryResults.getLimit()).isEqualTo(2);
        assertThat(queryResults.getOffset()).isEqualTo(1);
        assertThat(queryResults.getResults().size()).isEqualTo(2);

- 전체 조회를 통해 원하는 데이터를 가져올 수 있다.

- 조건 결과를 조회할 때와 전체 조회를 할 때 반환값이 다른 것을 확인 할 수 있다.

List<Member> result

QueryResults<Member>

- 집합
@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인 것을 확인 할 수 있는데, Tuple은 여러개의 타입이 있을 때 꺼내는 방식이다.


- 그룹
/*
    * 팀의 이름과 각 팀의 평균 연령을 구해라.
    * */
    @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);
    }

- join을 사용하면 기본적으로 inner join을 사용한다.

 

 

 

 

 

 

 

 

 

 

 

출처 : 인프런 - 김영한(실전! Querydsl)

 

728x90