Query DSL

Jiyeong Kim·2025년 3월 18일

TIL

목록 보기
24/24

사용방법

1. build.gradle 세팅

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)
 }
  • 이후 build.gradle을 반영해서 Q도메인 클래스가 생성되었는지 봐야한다. 이를 통해 설정이 올바르게 되었는지 판단할 수 있기 때문이다.

  • 상단에 build/generated/sources ~ 아래에 q로 시작하는 클래스가 생성되어야한다.
  • 나는 뜨지 않았고, 셋팅에는 문제가 없는 것을 보아 gradlew의 문제로 추정하고 새로 깔았다.

2. 일부 수정의 경우

문제 8번

  • JPQL로 작성된 findByIdWithUser 를 QueryDSL로 변경합니다.
  • 7번과 마찬가지로 N+1 문제가 발생하지 않도록 유의해 주세요!

빌드 그레이들을 셋팅했으니 config 패키지와, repository 패키지 순서대로 수정을 진행한다.

1. config

@Configuration
public class QueryDSLConfiguration {
  • 해당 클래스 안에 엔티티 매니저와, JPAQueryFactory를 빈으로 주입한다.

2. repository package

기존 레포지터리에 추가로 하려고했는데 실행이 되지 않았다.
다른 인터페이스를 새로 만들었다.

public interface TodoRepositoryCustom { 
     Optional<Todo> findByIdWithUserCustom(Long todoId);
 }
  • impl 파일 생성 및 수정

3. 새로운 API 생성의 경우

10. QueryDSL 을 사용하여 검색 기능 만들기

👉 일정을 검색하는 기능을 만들고 싶어요!
검색 기능의 성능 및 사용성을 높이기 위해 QueryDSL을 활용한 쿼리 최적화를 해보세요.
❗Projections를 활용해서 필요한 필드만 반환할 수 있도록 해주세요❗

  • 새로운 API로 만들어주세요.
  • 검색 조건은 다음과 같아요.
    • 검색 키워드로 일정의 제목을 검색할 수 있어요.
      • 제목은 부분적으로 일치해도 검색이 가능해요.
    • 일정의 생성일 범위로 검색할 수 있어요.
      • 일정을 생성일 최신순으로 정렬해주세요.
    • 담당자의 닉네임으로도 검색이 가능해요.
      • 닉네임은 부분적으로 일치해도 검색이 가능해요.
  • 다음의 내용을 포함해서 검색 결과를 반환해주세요.
    • 일정에 대한 모든 정보가 아닌, 제목만 넣어주세요.
    • 해당 일정의 담당자 수를 넣어주세요.
    • 해당 일정의 총 댓글 개수를 넣어주세요.
  • 검색 결과는 페이징 처리되어 반환되도록 합니다.

기본적인 API 생성하듯 진행

1. response dto

  • 다음의 내용을 포함해서 검색 결과를 반환해주세요.
    • 일정에 대한 모든 정보가 아닌, 제목만 넣어주세요.
    • 해당 일정의 담당자 수를 넣어주세요.
    • 해당 일정의 총 댓글 개수를 넣어주세요.

위의 조건 반영

2. controller

새로운 API로 만들어주세요.

  • 검색 조건은 다음과 같아요.
    • 검색 키워드로 일정의 제목을 검색할 수 있어요.
      • 제목은 부분적으로 일치해도 검색이 가능해요.
    • 일정의 생성일 범위로 검색할 수 있어요.
      • 일정을 생성일 최신순으로 정렬해주세요.
    • 담당자의 닉네임으로도 검색이 가능해요.
      • 닉네임은 부분적으로 일치해도 검색이 가능해요.
  • 검색 결과는 페이징 처리되어 반환되도록 합니다.
@GetMapping("/todos/search") //Lv.3-10
    public ResponseEntity<Page<TodoSearchResponse>> searchTodos(
            @RequestParam(defaultValue = "1") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(required = false) String title,
            @RequestParam(required = false) String start,
            @RequestParam(required = false) String end,
            @RequestParam(required = false) String nickname
    ) {
        return ResponseEntity.ok(todoService.searchTodos(page, size, title, start, end, nickname));
    }

3. Service

public Page<TodoSearchResponse> searchTodos(int page, int size, String title, String start, String end, String nickname) {
        Pageable pageable = PageRequest.of(page - 1, size);
        .
        .
        .
  • if절로 제목, 닉네임, 날짜를 조회할 수 있는 query dsl 작성
Page<TodoSearchResponse> todos = todoRepositoryCustom.findTodoWithCommentAndManagerCounts(pageable, title, start, end, nickname);
        return todos.map(todo -> new TodoSearchResponse(
                todo.getId(),
                todo.getTitle(),
                todo.getMangerCount(),
                todo.getCommentCount()
        ));

4. repository

  • TodoRepositoryCustom
Page<TodoSearchResponse> findTodoWithCommentAndManagerCounts(Pageable pageable, String title, String start, String end, String nickname);
  • TodoRepositoryImpl
@Override
    public Page<TodoSearchResponse> findTodoWithCommentAndManagerCounts(Pageable pageable, String title, String start, String end, String nickname) {
        QTodo todo = QTodo.todo;
        QComment comment = QComment.comment;
        QManager manager = QManager.manager;
        QUser user = QUser.user;
        .
        .
        .

트러블슈팅

Page<TodoSearchResponse> findTodoWithCommentAndManagerCounts(Pageable pageable, String title, String start, String end, String nickName);
  • " TodoSearchResponse " 위치에 에러 발생

  • 에러메세지 : Type 'org. hibernate. query. Page' does not have type parameters

  • 오류 원인 :
    org.springframework.data.domain.Page를 임포트 해야하나 org.hibernate.query.Page를 임포트함

  • 임포트 수정하여 해결

profile
해봅시다

0개의 댓글