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을 사용하는 방법에 대해서 알아보도록 하겠습니다.
'Programing > JPA' 카테고리의 다른 글
JpaRepository Custom / repository에 공통 사용 메서드 추가 (0) | 2023.07.27 |
---|---|
Querydsl vs Criteria API vs QueryMethod vs JPQL 비교 (2) | 2023.07.20 |
JPA Date or Timestamp 저장 시 유용한 어노테이션 (0) | 2023.05.16 |
JPA 에서 entity를 삭제하는 여러가지 방법과 차이 (0) | 2023.05.04 |
JPA Query Methods 정리 (0) | 2023.04.13 |
댓글