Spring

Spring Data JPA - QueryDSL 쿼리 작성하기

구티맨 2021. 10. 14. 12:48

목차

     

    Query 클래스

    쿼리를 작성하기 이전에 몇 가지 인터페이스와 클래스에 대해 간단히 살펴보겠습니다.

     

    JPQLQuery 인터페이스는 JPQL 쿼리를 위한 Query 인터페이스이며,

    JPAQuery 클래스는 JPQLQuery 인터페이스를 구현한 클래스이며, 쿼리를 작성하고 실행하는 역활을 합니다.

    JPAQueryFactory도 JPAQuery를 생성해주는 factory클래스입니다.

     

    결국은 JPAQuery를 사용하든, JPAQueryFactory를 사용하든 JPAQuery를 사용하는건 마찬가지 이지만,

     

    JPAQuery를 생성할 때 누가 더 간략하나 정도의 차이가 있어 코드 가독성 측면에서 Factory를 사용하는 것이 더 좋고,

     

    많은 snippets 코드들이 Factory를 사용하므로 Factory를 사용하는 것이 좋다고 할 수 있지만

     

    어디까지나 개인의 선택에 따라 사용을 하면 되는 것 같습니다.

     

    참조 : https://stackoverflow.com/questions/62569696/difference-between-jpaquery-and-jpaqueryfactory/62570145#62570145

     


     

    QueryDSL 사용법

    쿼리 결과 가져오기

    @Autowired
    JPAQueryFactory jpaQueryFactory;
        
    ...
    
    
    QMember member = QMember.Member;
            
    jpaQueryFactory.select(member)
                    .from(member)
                    .fetch();
    • fetch : 조회 대상 전체를 반환
    • fetchOne : 조회 대상이 1건일 경우 한건만 반환( 2건 이상일 경우, 예외 발생 )
    • fetchFirst : 조회 대상을 1건만 반환( (this.limit(1L)).fetchOne() -> limit 1으로 한건만 가져오도록 구현 되어 있습니다. )
    • fetchCount : 조회 대상의 개수를 반환합니다.
    • fetchResults : 조회 대상의 데이터와 전체 개수를 포함하는 QueryResults를 반환합니다.
    fetchAll, fetchJoin에 대해서는 별도 포스팅에서 다루도록 하겠습니다.

    프로젝션과 쿼리 대상지정( SELECT, FROM )

    QMember member = QMember.Member;
            
    jpaQueryFactory.select(member)
                    .from(member)
                    .fetch();
    jpaQueryFactory
    .selectFrom(segmentMeta)
    .fetch();

    member의 모든 컬럼 값을 가지고 옵니다.

    조건( Where )

    조인( 연관관계 없는 테이블 )

    jpaQueryFactory.select(member.name, school.addr)
                        .from(member)
                        .innerJoin(school).on(member.schoolId.eq(school.schoolId))
                        .fetch();

    연관 관계 없는 테이블 간에 JOIN을 해서 필요한 정보를 가져올 수 있습니다.

    조건( WHERE )

    // WHERE member.name LIKE '%JACK%'
    jpaQueryFactory.select(member)
                        .from(member)
                        .where(member.name.upper().contains("JACK"))
                        .fetch();
                        
    // WHERE member.name LIKE '%JACK%' AND member.addr LIKE '%seoul%'
    jpaQueryFactory.select(member)
                        .from(member)
                        .where(member.name.upper().contains("JACK"), member.addr.contains("seoul"))
                        .fetch();

    동적 조건( WHERE )

    com.querydsl.core.BooleanBuilder 를 사용하여 동적으로 조건을 생성할 수 있습니다.

    // WHERE member.name LIKE '%kim%' AND member.addr LIKE '%seoul%'
    BooleanBuilder builder = new BooleanBuilder();
    builder.and(member.name.contains('kim'));
    builder.and(member.addr.contains('seoul'));
    
    jpaQueryFactory.select(member)
                        .from(member)
                        .where(builder)
                        .fetch();