JPA 프로젝트를 진행할때 짧은 쿼리문 두개를 네이티브 쿼리를 이용해 작성을 했었다. 헌데 이것은 정말 JPA를 너무 모르고 썼다는 증거임
쿼리문 쓰기 싫어서 나온게 JPA인데 네이티브 쿼리를 쓰다니!!!!
그럴거면 뭣하러 JPA를 쓰냐
그럼 네이티브 쿼리 말고 다른거 뭐 써야하죠?
JPQL과 QueryDSL
코드 작성 방식
JPQL: 문자열 기반 쿼리
QueryDSL: 자바 코드 기반의 type-safe 빌더 API
검증 가능성
- JPQL: 실행 전 문법 검증 불가능
- QueryDSL: 코드상으로 문법 오류 검증 가능
IDE 지원
- JPQL: 문법 자동완성 기능 없음
- QueryDSL: 문법 자동완성, import 자동관리 등
타입 안정성
- JPQL: 타입 오류 runtime 시 발생
- QueryDSL: 컴파일 시 타입 체크
가독성
- 복잡한 동적 쿼리 작성 시 QueryDSL이 더 높음
결론적으로 QueryDSL은 JPQL의 단점을 보완하고 실용성을 높여줍니다. 타입 안전성, IDE 지원 등을 활용할 수 있어 생산성이 높아집니다.
문법 오류 찾기 쉬움, 문법 자동완성 해줌 이라는 글에 꽂혀서 QueryDSL을 써보기로 했다.
SpringBoot3,
Gradle
환경 설정을 시작해보도록 하자.
그 전에 SpringBoot2에다가 적용을 했던지라 그것도 같이 정리를 해보도록 하겠다.
2,3 환경설정 하는 법이 달라서 좀 헤맸더랬다.
SpringBoot2( 사이트 )는 위에 사이트를 보고 그대로 복붙하면 되고
SpringBoot3는 좀 다르지 ( 참고 사이트 )
// 가장 상위에 추가
buildscript {
ext {
queryDslVersion = "5.0.0"
}
}
dependencies {
//querydsl 설정 추가
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
}
// Querydsl 설정
def generated = 'src/main/generated'
// querydsl QClass 파일 생성 위치를 지정
tasks.withType(JavaCompile) {
options.getGeneratedSourceOutputDirectory().set(file(generated))
}
// java source set 에 querydsl QClass 위치 추가
sourceSets {
main.java.srcDirs += [ generated ]
}
// gradle clean 시에 QClass 디렉토리 삭제
clean {
delete file(generated)
}
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import jakarta.persistence.EntityManager; // javax 아니고 jakarta이다!!
@Configuration
public class QueryDslConfig {
@Bean
JPAQueryFactory jpaQueryFactory(EntityManager em) {
return new JPAQueryFactory(em);
}
}
뭐가 자꾸 안되면 build clean , build , 프로젝트 재시작을 해주자
그리고 위에 사이트 보고 그대로 따라해주면 되는데 여기서 이해가 안갔던 부분이 Quser 였음.
대체 Quser는 어디서 import를 해오는거지? 하고 있었는데 어... 자동으로 된다.
@Override
public List<User> findUserList() {
return queryFactory
.selectFrom(QUser.user) // Quser는 무엇인가???
.fetch();
}
앞에서 우리는 gradle 설정을 여러개 해주었잖아 그것 때문임