본문 바로가기
개발/JPA, Querydsl

Querydsl의 이론적인 부분

by hamcheeseburger 2022. 10. 31.

About

Querydsl 이란?

  • Querydsl은 타입에 안전한 방식으로 HQL 쿼리를 실행하기 위한 목적으로 탄생.
  • 현재는 JPA, JDO, JDBC, Lucene, Hibernate Search, MongoDB, 콜렉션 그리고 RDFBean을 지원.

원칙

  • 타입 안정성
    • 기존의 HQL(Hibernate HQL)은 String 타입의 연결로 구현할 수 밖에 없는데, 이는 컴파일 시점에 문법 오류, 오타를 잡아줄 수 없음.
    • Querydsl은 도메인 타입의 프로퍼티를 반영해서 생성한 쿼리 타입을 이용해서 쿼리를 작성.
  • 일관성
    • 기반 기술에 상관 없이 (JPA를 사용하든, JDBC를 사용하든 상관없이) 쿼리 경로와 오퍼레이션이 동일.
    • Query interface는 공통의 상위 인터페이스를 갖게 됨.
      • (뇌피셜) com.querydsl.jpa.impl 에 포함되어있는 JPAQuery 클래스는 결국에 com.querydsl.core에 있는 상위 interface를 상속받는다. 그렇다면 JPA가 아닌 다른 기반 기술을 위한 JPAQuery와 비슷한 클래스가 있을 것이고, 해 당 클래스가 공통된 상위 interface의 구현체이지 아닐까 하는 생각이 든다.
       

설정

방법1. gradle plugin 사용 (비추천)

@Entity 가 붙은 클래스를 QClass로 변경해야 하는데, 이 때 원래는 변환 스크립트를 작성해주어야한다. 이러한 작업이 번거로우니 gradle plugin을 사용했던 것이다.

그러나 IDE 버전과 의존성들의 빠른 업데이트로 인해 작성한 스크립트가 제대로 동작하지 않는 경우가 종종 발생한다. 그 중 Querydsl JPA plugin이 대표적이다.

현재 Querydsl JPA plugin은 2018.7 에 출시된 1.0.10 를 마지막으로 더이상 업데이트가 없다.

현재는 gradle에서 annotationProcessor를 제공해주므로, gradle plugin을 사용하기 보다는 아래의 방법을 추천한다고 한다.

방법2. annotationProcessor 사용 (추천)

Querydsl은 Springboot starter에 포함되어있지 않으므로 gradle에 추가 설정이 필요하다.

dependencies {
	// 1. querydsl을 의존한다.
    implementation 'com.querydsl:querydsl-jpa'
    
    // 2. JPAAnnotationProcessor를 지정한다. (Q파일을 생성해준다.)
    annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jpa"
    
    // 3. java.lang.NoClassDefFoundError(javax.annotation.Entity) 발생 대응
    annotationProcessor "jakarta.persistence:jakarta.persistence-api"
    
    // 4. java.lang.NoClassDefFoundError (javax.annotation.Generated) 발생 대응
    annotationProcessor "jakarta.annotation:jakarta.annotation-api"
}

원래는 사용할 AnnotationProcessor를 gradle에 직접 명시를 해주었어야 한다(JPAAnnotationProcessor 등) annotationProcessor 설정 방법 부터는 annotationProcessor 에 작성한 것을 기반으로 사용할 AnnotationProcessor를 알아서 지정해준다. 위의 설정에서는 JPAAnnotationProcessor가 자동으로 지정된다.

적용 후 build하면, build/generated/sources/annotationProcessor 에 각 entity파일에 대칭되는 Q파일이 생성된다.

동작과정

gradle 설정 정보에 따라 지정된 AnnotationProcessor가 동작하면서 QClass를 생성하게 된다. 위의 설정은 JPAAnnotationProcessor가 지정된 것이며, 프로젝트 내에 @Entity 가 붙은 클래스를 탐색하여 QClass를 생성하게 된다.

출처 :  https://www.youtube.com/watch?v=gRqyzi9VGYc

QClass

QClass는 Static한 Meta Class라고 이야기 할 수 있다. AnnotationProcessor가 build 시 자동으로 생성을 해주며, 해당 클래스로 Querydsl의 쿼리문을 생성할 수 있다.

import static com.woowacourse.f12.domain.product.QProduct.product;

public class ProductRepositoryCustomImpl implements ProductRepositoryCustom {

    // 생성자 생략

    @Override
    public Slice<Product> findWithoutSearchConditions(final Pageable pageable) {
        final JPAQuery<Long> jpaLongQuery = jpaQueryFactory.select(product.id)
                .from(product)
                .orderBy(makeOrderSpecifiers(product, pageable))
                .offset(pageable.getOffset())
                .limit(pageable.getPageSize() + 1);
				// 이하 생략
    }
}

위 코드의 import 구문을 보면 QProduct를 확인할 수 있다.

 

이러한 Meta Class를 사용하는 것은 QueryDSL만이 갖는 특징은 아니다.

JPA Static MetaModel Generator 를 사용하여 MetaModel Class를 자동으로 생성할 수 있으며, 이는 JPA Criteria API에서 사용할 수 있다.

 

 

출처

이전 댓글