본문 바로가기

Spring/Querydsl

Querydsl- 정렬과 페이징

예시 초기 조건

package study.querydsl;

@SpringBootTest
@Transactional
public class QuerydslBasicTest {
    @Autowired
    EntityManager em;
    JPAQueryFactory queryFactory;

    @BeforeEach //각 테스트마다 데이터 주입
    public void each(){
        queryFactory = new JPAQueryFactory(em);

        Team teamA = new Team("teamA");
        Team teamB = new Team("teamB");
        em.persist(teamA);
        em.persist(teamB);

        Member member1 = new Member("member1", 10, teamA);
        Member member2 = new Member("member2", 20, teamA);
        Member member3 = new Member("member3", 30, teamB);
        Member member4 = new Member("member4", 40, teamB);
        
        em.persist(member1);
        em.persist(member2);
        em.persist(member3);
        em.persist(member4);
    }
}

여기에 나오는 모든 예시들은 위와 같은 초기 설정을 따른다. member1~4와 team1,2가 persist 되어있다. 이 코드는 단순화를 위해서 다른 테스트 코드에는 적지 않았다.

정렬

 orderBy

package study.querydsl;

public class QuerydslBasicTest {
    /**
     *  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)) // 나이가 100인 멤버를 조회하되,
                // orderBy: 정렬순서 정하기
                .orderBy(member.age.desc(), member.username.asc().nullsLast())  // 나이는 내림차순으로, 이름은 올림차순으로 정렬하되, 이름이 null이라면 마지막에 출력.
                .fetch();
//        List<Member> JpqlFindResult = em.createQuery("select m from Member m " +
//                        "where m.age = 100 " +
//                        "order by m.age desc , m.username asc nulls last ", Member.class)
//                .getResultList();
        for (Member findMember : result) {
            System.out.println("findMember = " + findMember);
        }

        Member findMember1 = result.get(0);
        Member findMember2 = result.get(1);
        Member findMemberNull = result.get(2);

        org.junit.jupiter.api.Assertions.assertEquals(findMember1.getUsername(),"member5");
        org.junit.jupiter.api.Assertions.assertEquals(findMember2.getUsername(),"member6");
        org.junit.jupiter.api.Assertions.assertEquals(findMemberNull.getUsername(),null);
    }
}

 querydsl에서는 orderBy( ) 메서드를 통해서 조회한 데이터들을 정렬하여 반환할 수 있다. 테스트 코드 sort()를 보면 다음과 같은 조회 쿼리를 볼 수 있다. orderBy()의 파라미터로는 정렬 조건이 들어간다.

 조회쿼리

List<Member> result = queryFactory
        .selectFrom(member)
        .where(member.age.eq(100)) // 나이가 100인 멤버를 조회하되,
        // orderBy: 정렬순서 정하기
        .orderBy(member.age.desc(), member.username.asc().nullsLast())  // 나이는 내림차순으로, 이름은 올림차순으로 정렬하되, 이름이 null이라면 마지막에 출력.
        .fetch();

member 를 조회하되 where를 사용해서 나이가 100인 member만 조회를 한다. (참고로 여기서 member는 QMember.member이다)

그러고 나서 orderBy를 통해서 정렬을 하는데 그 조건은 다음과 같다.

  • member.age.desc(): member의 age를 내림차순으로 정렬한다.
  • member.username.asc().nullLast(): member의 username을 오름차순으로 정렬한다. 단 null인 경우 마지막으로 정렬한다.

이를 동일하게 jpql로 나타내면 다음과 같다.

List<Member> JpqlFindResult = em.createQuery("select m from Member m " +
                        "where m.age = 100 " +
                        "order by m.age desc , m.username asc nulls last ", Member.class)
                .getResultList();

페이징

 offset, limit

package study.querydsl;

@SpringBootTest
@Transactional
public class QuerydslBasicTest {
    @Test
    public void paging1(){
        List<Member> result = queryFactory
                .selectFrom(member)
                .orderBy(member.username.desc())
                .offset(1) // 1번부터
                .limit(2)  // 최대 2개 가져옴
                .fetch();
        for (Member member1 : result) {
            System.out.println("member1 = " + member1);
        }
    }
}
List<Member> resultList = 
                em.createQuery("select m from Member m order by m.username desc",
                                Member.class)
                .setFirstResult(1) // 1번부터
                .setMaxResults(2)  // 최대 2개 가져옴
                .getResultList();

 offset()과 limit() 메서드를 통해서 페이징을 할 수 있다. 이는 jpql의 setFirstResult()와 setMaxResult()에 각각 대응한다.

따라서 paging1()의 querydsl 쿼리를 jpql로 변환한다면 다음과 같을 것이다.

 

 따라서 다음 페이징을 정리하면 다음과 같다.

  • offset( ) [Querydsl] == setFirstResult( ) [Jpql] : 페이징을 시작할 데이터의 인덱스 지정
  • limit( ) [Querydsl] == setMaxResult( ) [Jpql]: 페이징으로 가져 올 최대 데이터 개수

 

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

Querydsl- 조인  (0) 2023.07.27
Querydsl- 집합  (0) 2023.07.26
Querydsl- Q 인스턴스  (0) 2023.07.22
Querydsl- Jpql과 Querydsl 비교  (0) 2023.07.22
Querydsl- build.gradle 설정  (0) 2023.07.22