본문 바로가기
JPA/Querydsl

Querydsl 02 - 기본문법(Q타입, 검색조건, 결과조회)

by 킹차니 2022. 1. 16.

JPQL와 Querydsl을 비교하며 기본적인 문법을 알아보자.

 

먼저 username으로 select하는 JPQL을 보자.

@Test
void startJPQL() {
    //member1을 찾아라.
    Member findMember =
            em.createQuery("select m from Member m where m.username = :username", Member.class)
            .setParameter("username", "member1")
            .getSingleResult();
    Assertions.assertThat(findMember.getUsername()).isEqualTo("member1");
}
//->테스트 성공

이때 날아간 쿼리문은 아래와 같다.

    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_.username=?

 

이번에는 Querydsl로 username으로 조회를 해보자.

@Test
void startQuerydsl() {
    JPAQueryFactory queryFactory = new JPAQueryFactory(em);
    QMember m = new QMember("m");
    Member findMember = queryFactory
                            .select(m)
                            .from(m)
                            .where(m.username.eq("member1"))//파라미터 바인딩 처리
                            .fetchOne();
    Assertions.assertThat(findMember.getUsername()).isEqualTo("member1");
}

EntityManager로 JPAQueryFactory생성

Querydsl은 JPQL빌더

JPQL : 문자(실행 시점 오류), Querydsl : 코드 (컴파일 시점 오류)

JPQL : 파라미터 바인딩 직접, Querydsl : 파라미터 바인딩 자동 처리

 

날아간 쿼리는 위의 JPQL에서와 같다.

    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_.username=?

 

 


Q타입 인스턴스

Q타입 인스턴스를 사용하는 방법은 3가지가 있다.

 

1. new를 사용하는 방법

/*1번 방법*/ QMember m = new QMember("m");

Member findMember = queryFactory
        .select(m)
        .from(m)
        .where(m.username.eq("member1"))
        .fetchOne();

제일 권장하지 않는 방법이다.

 

 

2. static 필드 사용하기

/*2번 방법*/ QMember m = QMember.member;//더 짧은 방법

Member findMember = queryFactory
        .select(m)
        .from(m)
        .where(m.username.eq("member1"))
        .fetchOne();

 

 

3. static 필드를 import하여 사용하는 방법.

/*3번 방법 - 제일 권장하는 방법*/
import static study.querydsl.entity.QMember.member;

Member findMember = queryFactory
        .select(member)
        .from(member)
        .where(member.username.eq("member1"))
        .fetchOne();

 


검색 조건 쿼리

 

아래와 같이 검색 조건이 2개 이상일 때 and를 사용하여 검색 조건을 추가할 수 있다.

@Test
void search1() {
    Member findMember = queryFactory
            .selectFrom(member)//요렇게 select + from 합치기 가능
            .where(member.username.eq("member1")
                    .and(member.age.eq(10)))//and 또는 or로 체인걸기
            .fetchOne();

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

• 검색 조건은 .and(), .or() 를 메서드 체인으로 연결할 수 있다.

참고 : select 와 from을 위의 search1처럼 합칠 수 있음

 

Querydsl은 JPQL이 제공하는 모든 검색조건을 제공한다.

member.username.eq("member1") // username = 'member1'
member.username.ne("member1") // username != 'member1'
member.username.eq("member1").not() // username != 'member1'
member.username.isNotNull() // 이름이 is not null
member.age.in(10, 20) // age in (10,20)
member.age.notIn(10, 20) // age not in (10, 20)
member.age.between(10,30) // between 10, 30
member.age.goe(30) // age >= 30
member.age.gt(30) // age > 30
member.age.loe(30) // age <= 30
member.age.lt(30) // age < 30
member.username.like("member%") // like 검색
member.username.contains("member") // like ‘%member%’ 검색
member.username.startsWith("member") // like ‘member%’ 검색 ...

 

또한 아래와 같이 and조건을 파라미터로 처리할 수 있다.

@Test
void searchAndParam() {
    Member findMember = queryFactory
            .selectFrom(member)
            .where(
            		//and조건 2개 파라미터
                    member.username.eq("member1"), member.age.eq(10) 
            )
            .fetchOne();

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

• where에 파라미터로 검색조건을 추가하면 AND조건이 추가된다.

• 이 경우 null값은 무시 -> 메서드 추출을 총해서 동적쿼리를 깔끔하게 만들 수 있다.

 


결과 조회

• fetch() : 리스트 조회, 데이터가 없으면 빈 리스트를 반환한다. (null아님을 보장)

• fetchOne() :단 건 조회

  - 결과가 없으면 null을 반환.

  - 결과가 둘 이상이면 com.querydsl.core.NonuiqueResultException

• fetchFirst : limit(1).fetchOne() 와 같닫.

이들을 사용해보자.

@Test
void resultFetch() {
    //다수 조회
    List<Member> fetch = queryFactory.selectFrom(member)
                                     .fetch();
    //단건 조회
    Member fetchOne = queryFactory.selectFrom(member)
                                  .fetchOne(); //-> 얘는 지금 모든 member를 조회하므로 에러발생
                                  //하여 아래와 같이 unique한 조건을 추가해야함
	Member fetchOne = queryFactory.selectFrom(member)
    								.where(member.username.eq("member1"))
					                .fetchOne();                                  
                                  
    //처음 한 건 조회
    Member fetchFirst = queryFactory.selectFrom(QMember.member)
                                    .fetchFirst();
}

수행된 쿼리 :  위에서 부터

//List
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_

 

//단건 조회
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_.username=?

 

// 맨 처음 하나 조회
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_ limit ?

 

 

 

 

김영한님의 인프런 강의와 PDF를 바탕으로 정리하였습니다.