패키지 구조를 개선하는 리팩토링 과정에서 JPQL로 작성된 부분들에 문제가 발생했습니다.
바로, JPQL 쿼리에서 DTO 클래스 경로 참조가 깨지는 현상인데, 뭐 문자열이니까 어찌보면 당연한 결과기도 합니다.
짧게 설명해보겠습니다.
문제 상황
계층형 패키지 구조에서 도메인 중심 패키지 구조로 전환하면서 아래와 같은 JPQL 쿼리가 동작하지 않았습니다:
@Query("SELECT new com.appcenter.timepiece.dto.project.ProjectThumbnailResponse(p, c.thumbnailUrl) " +
"FROM Project p " +
"INNER JOIN MemberProject mp ON mp.projectId = p.id " +
"LEFT JOIN Cover c ON p.coverId = c.id " +
"WHERE mp.memberId = :memberId " +
"AND p.isDeleted = false AND mp.isStored = false " +
"ORDER BY p.updatedAt DESC")
Page<ProjectThumbnailResponse> fetchProjectThumbnailResponse(Pageable pageable, Long memberId);
ProjectThumbnailResponse 클래스가 com.appcenter.timepiece.dto.project 패키지에서 com.appcenter.timepiece.domain.project.dto 패키지로 이동했기 때문입니다.
원인
JPQL 쿼리는 문자열로 정의되며, 이 문자열에는 클래스의 전체 경로(FQCN)가 하드코딩되어 있습니다. 따라서 IDE의 자동 리팩토링 기능이 이 부분을 감지하지 못합니다.
해결 방법
모든 JPQL 쿼리를 수동으로 업데이트하여 새 패키지 경로를 반영해야 합니다:
@Query("SELECT new com.appcenter.timepiece.domain.project.dto.ProjectThumbnailResponse(p, c.thumbnailUrl) " +
"FROM Project p " +
"INNER JOIN MemberProject mp ON mp.projectId = p.id " +
"LEFT JOIN Cover c ON p.coverId = c.id " +
"WHERE mp.memberId = :memberId " +
"AND p.isDeleted = false AND mp.isStored = false " +
"ORDER BY p.updatedAt DESC")
Page<ProjectThumbnailResponse> fetchProjectThumbnailResponse(Pageable pageable, Long memberId);
JPQL은 편리해서 자주 써왔는데 이러한 문제를 마주한 건 또 처음이라 기억할 겸 적어봤습니다.
패키지 구조 변경 시 이러한 하드코딩된 참조들을 신경써줘야 하는데,,
음.. 역시 QueryDSL을 써야하나..
'개발 > 짧 지식' 카테고리의 다른 글
세션은 어디에 저장될까? (HttpSession, Cookie and Session) (0) | 2023.08.08 |
---|---|
클래스 분리 시, #include 문의 위치 (0) | 2022.11.18 |
콜백 메소드(Callback Method)는 뭘까. (0) | 2022.11.16 |
Android Lifecycle (0) | 2022.11.14 |
댓글