Tools & Libraries/Querydsl

[Querydsl] Querydsl 기본문법 2 (검색 조건, 결과 조회, 정렬, 페이징)

대기업 가고 싶은 공돌이 2024. 9. 3. 05:30

검색 조건 쿼리

@Test
public void search(){
    Member findMember = queryFactory
            .selectFrom(member)
            .where(member.username.eq("member1")
                    .and(member.age.eq(10)))
            .fetchOne();

    Assertions.assertThat(findMember.getUsername()).isEqualTo("member1");
}

 

우선 다음과 같이 테스트 코드를 작성해주었다.

 

where절에서는 위와 같이 메소드 형식으로 and, or 을 비롯한 무수하게 많은 검색 조건을 제공한다.

 

  1. equal, not equal
    • member.username.eq("member1")
    • member.username.ne("member1")
  2. isNotNull
    • member.username.isNotNull();
  3. in, between
    • member.age.in(10,20)
    • member.age.notIn(10,20)
    • member.age.between(10,30)
  4. 부등호
    • member.age.goe(30)  // age>= 30
    • member.age.gt(30)  // age> 30
    • member.age.loe(30)  // age<= 30
    • member.age.lt(30)  // age< 30
  5. like
    • member.username.like("member%")
    • member.username.contains("member") // like %member% 과 동일
    • member.username.startWith("member") // like %member 

검색 조건 쿼리 추가 팁

and 같은 경우엔 다음과 같이 and를 생략하고 ,으로 넘겨줄 수도 있다.

@Test
public void search(){
    JPAQueryFactory queryFactory = new JPAQueryFactory(em);

    Member findMember = queryFactory
            .selectFrom(member)
            .where(member.username.eq("member1")
                    ,member.age.eq(10))
            .fetchOne();

    Assertions.assertThat(findMember.getUsername()).isEqualTo("member1");
}

 

결과 조회

  • fetch(): 리스트 조회, 데이터 없으면 빈 리스트 반환
List<Member> fetch = queryFactory.selectFrom(member)
        .fetch();
  • fetchOne(): 단 건 조회
    • 결과가 없으면 null 반환
    • 결과가 둘 이상이면 com.querydsl.core.NonUniqueResultException 호출
Member fetchOne = queryFactory.selectFrom(member)
        .fetchOne();
  • fetchFirst(): limit(1).fetchOne() //리미트를 걸면서 페치하는 것 
Member fetchFirst = queryFactory
        .selectFrom(member)
        .fetchFirst();
  • fetchResults(): 페이징 정보 포함, total count 쿼리 추가 실행
    • 페이징 쿼리를 같이 날리면서 total count를 같이 가져온다.
    • 복잡한 페이징 쿼리를 날릴 때는 해당 메소드를 사용하면 성능이 떨어지기 때문에 사용하면 안 된다.
QueryResults<Member> results = queryFactory
        .selectFrom(member)
        .fetchResults();
results.getTotal();
List<Member> content = results.getResults();

results를 가져온 후 getResults를 해야 안에 담긴 Member List를 가져올 수 있다.

 

  • fetchCount(): count 쿼리로 변경해서 count 수만 조회하는 기능
long l = queryFactory
        .selectFrom(member)
        .fetchCount();

 

위의 코드를 실행 시키면 select count(member1) 쿼리가 나간 것을 확인할 수 있다.

 

정렬

/**
 *회원 정렬 순서
 * 1. 회원 나이 내림차순
 * 2. 회원 이름 올림차순
 * 3. 2에서 회원 이름이 없으면 마지막에 출력 (nulls last 기능)
 */
@Test
public void sort(){
    JPAQueryFactory queryFactory = new JPAQueryFactory(em);
    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);

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


}

 

order by 절 안에서 다음과 같이 desc, asc, nullsLast, nullsFirst 등의 옵션을 전부 사용할 수 있다.

 

페이징

@Test
public void paging1(){
    JPAQueryFactory queryFactory = new JPAQueryFactory(em);

    List<Member> result = queryFactory.selectFrom(member)
            .orderBy(member.username.desc()) // order by를 사용하는 이유는 결과 확인을 위해서
            .offset(1)
            .limit(2)
            .fetch();

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

 

querydsl에서는 위와 같이 offset과 limit를 통해 페이징을 지원한다.

 

만약 토탈 카운트도 한 번에 알아내고 싶다면 다음과 같이 쿼리를 작성할 수도 있다.

@Test
public void paging1(){
    JPAQueryFactory queryFactory = new JPAQueryFactory(em);

    QueryResults<Member> results = queryFactory.selectFrom(member)
            .orderBy(member.username.desc()) // order by를 사용하는 이유는 결과 확인을 위해서
            .offset(1)
            .limit(2)
            .fetchResults();
    
    Assertions.assertThat(results.getTotal()).isEqualTo(4);
    Assertions.assertThat(results.getLimit()).isEqualTo(2);
    Assertions.assertThat(results.getResults().size()).isEqualTo(2);
}

 

카운트 쿼리를 조인을 하지 않고 간단하게 작성할 수 있을 경우엔 위의 코드를 사용하지 않고,

카운트 쿼리를 따로 작성하여 성능을 향상시켜야 한다.

 

참고 영상: 김영한 실전! Querydsl