Springboot 2.x + queryDSL 설정 방법
JPA를 사용하게 되면 Query method를 사용하면 간단한 조건의 작업들은 가능하지만 복잡한 쿼리로 작성되어야하는 로직의 경우 한계가 있습니다. 물론 어느정도 가능은 하겠지만 query method의 길이가 엄청나게 길어지겠죠.
이를 보완하기 위해 @Query, JPQL 를 사용하도 합니다. 하지만 문자열을 + 로 연결해야 하며 가독성도 떨어지고, 유지관리에 어려움이 있습니다.
1. Query method
List<L_OP_ATND> findByKeyUserIdAndKeyAtndYmdBetweenOrderByKeyAtndYmd(String UseId, Date first, Date last);
2. @Query
@Query(value = "select count(*)"
+ " from ("
+ " select *"
+ " from ("
+ " select 'ACT1' as atvtNm"
+ " , 1 as atvtCd"
+ " , t2.cd_nm as status"
+ " , t1.rct_dt"
+ " , t1.rtn_dt"
+ " , t3.venue_nm"
+ " from schema.l_op_user_mucn t1"
+ " left join kt_carbon.m_op_cd t2 on (t2.cd_grp_id = 'CD0006' and t2.cd_id = t1.rct_rtn_cd)"
+ " left join kt_carbon.g_op_venue t3 on (t3.venue_sqno = t1.venue_sqno)"
+ " where t1.user_id = :userId"
+ " and t1.rct_dt between :stDate and :edDate"
+ " union all"
+ " select 'ACT2' as atvtNm"
+ " , 2 as avtvCd"
+ " , 'save' as status"
+ " , null as rct_dt"
+ " , null as rtn_dt"
+ " , null as venune_nm"
+ " from schema.l_op_hike"
+ " where user_id = :userId"
+ " and crt_ymd between :stDate and :edDate"
+ ") st where st.atvtCd in :atvtCd) t", nativeQuery = true)
int findActivityLogListCount(@Param("userId") String userId, @Param("atvtCd") List<Integer> atvtCd,
@Param("stDate") Date stDate, @Param("edDate") Date edDate);
이런 문제점(?!) 때문에 mybatis를 혼용해서 사용하는 경우도 있습니다.
개발하기는 편해지겠지만, 쿼리 의존적이 되고, 컴파일 시점에 오류를 파악하기도 힘들죠.
이런 단점들을 보완하면서 JPA를 좀 더 파워풀 하게 사용하기 위해 나온 것이 queryDSL입니다.
3. QueryDSL
QCat cat = QCat.cat;
QCat mate = new QCat("mate");
QCat kitten = new QCat("kitten");
queryFactory.selectFrom(cat)
.innerJoin(cat.mate, mate)
.leftJoin(cat.kittens, kitten)
.fetch();
Unified Queries for Java.
Querydsl is compact, safe
and easy to learn.
QueryDSL의 슬로건 입니다.
Java용 통합쿼리. 작고 안전하며 배우기 쉽다.
QueryDSL은 Java JPA, MongoDB 및 SQL을 포함하여 여러 백엔드에 대해 형식이 안전한 SQL 유사 쿼리를 구성할 수 있는 프레임워크 입니다.
4. QueryDSL 설정방법
4.1 build.gradle 설정
// springboot 2.6 이상에서는 5.0.0 버전을 사용
buildscript {
ext {
queryDslVersion = "5.0.0"
}
}
plugins {
.
.
.
//추가
id "com.ewerk.gradle.plugins.querydsl" version "1.0.10"
}
dependencies {
.
.
.
//queryDSL 의존성 추가
implementation "com.querydsl:querydsl-jpa:${queryDslVersion}"
implementation "com.querydsl:querydsl-apt:${queryDslVersion}"
.
.
.
}
//--------------------queryDSL 관련 추가----------------------------
def querydslDir = "$buildDir/generated/querydsl"
querydsl {
jpa = true
querydslSourcesDir = querydslDir
}
sourceSets {
main.java.srcDir querydslDir
}
configurations {
querydsl.extendsFrom compileClasspath
}
compileQuerydsl {
options.annotationProcessorPath = configurations.querydsl
}
위와같이 build.gradle 을 추가해줍니다. 추가 후 IDE를 재실행 해줍니다.
4.2 compileQuerydsl 실행
IDE를 재실행 후 Gradle > Tasks > other 을 보게되면 compileQuerydsl이 생긴 것을 확인하실 수 있습니다.
우선 Gradle > Tasks > build > clean 을 해주시고, 그 후에 other > compileQuerydsl을 실행해 주세요.
그럼 project > build > generated 에 entity들이 자동으로 생성된 것을 확인하실 수 있습니다.
4.3 QuerydslConfig 작성
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
@Configuration
public class QuerydslConfig {
@PersistenceContext
private EntityManager entityManager;
@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(entityManager);
}
}
repository에서 jpaQueryFactory를 쓰기위한 config 설정을 합니다.
이제 Querydsl을 사용할 준비가 끝났습니다.
다음 포스팅에서는 실제 .Querydsl을 사용하는 방법에 대해서 알아보도록 하겠습니다.