개괄
프로젝트 내의 jpql로 이루어진 조회 / 수정 쿼리들을 Querydsl을 이용한 쿼리로 migration하는 날
오늘 갑자기 CQS 원칙을 지키고 싶어져서 다음과 같이 Repository를 만들어 주었다.
repository
|-ProjectRepository
|-ProjectViewRepositoryCustom
|-ProjectViewRepositoryImpl
그리고 ProjectRepository 안의 userId로 projectResponseDto를 찾는 다음과 같은 쿼리도 변경해주어야 했다.
- ProjectRepository
@Query("select new com.ddalggak.finalproject.domain.project.dto.ProjectBriefResponseDto(p.projectId, p.projectTitle, p.thumbnail) from Project p join p.projectUserList pu where pu.user.userId = :userId")
List<ProjectBriefResponseDto> findAllinDtoByUserId(Long userId);
를
-ProjectViewRepositoryCustom
List<ProjectBriefResponseDto> findProjectAllByUserId(Long userId);
-ProjectViewRepositoryImpl
@Override
public List<ProjectBriefResponseDto> findProjectAllByUserId(Long userId) {
return queryFactory.select(new QProjectBriefResponseDto(
project.projectId,
project.projectTitle,
project.thumbnail
))
.from(project)
.join(project.projectUserList, projectUser)
.where(projectUser.user.userId.eq(userId))
.fetch();
}
분명히 연관관계도 문제가 없었고, 모든게 잘 되었다고 생각했는데 뜻하지 않은 오류를 만났다.
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'projectController' defined in file [~/ProjectController.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'projectService' defined in file [~/ProjectViewRepositoryCustom.findProjectAllByUserId(java.lang.Long)! No property 'userId' found for type 'Project'
ProjectViewRepositoryCustom 내부에 있는 findProjectAllByUserId 메소드의 파라미터로 받는 userId가 Project 내부에 있지 않아 UnsatisfiedDependencyException이 걸린 것이었다.
아니 그럼 Querydsl에서는 join문 못쓰나? 라고 생각해봤지만 그럴 리가 없었다.
그렇다고 user의 id값을 projectdto에 넣어주는것도 말이 되지 않았다.
그래서 Project 안에 있는 ProjectUser라는 행위 엔티티에서 User를 뽑아내어 어떻게든 UserId와 연결지어주려는
장장 3시간의 혈투가 시작되었다.
join문을 걸었다가 inner join을 걸었다가 join on을 걸었다가 참 많은 삽질 끝에 메소드 구현체를 지워봤는데도 똑같은 오류가 떴다.
결국
List<ProjectBriefResponseDto> findProjectAllByUserId(Long userId);
이 문장에서 오류가 있던 것이었는데, 이걸 어떻게 고치나 열심히 고민하다가 결국 흑마법을 사용하기로 결심했다.
그래서 혹시 Project와 Repository의 연결에 문제가 있는게 아닐까 싶어서
ProjectViewRepositoryCustom -> ProjectRepositoryCustom으로 리팩터링해봤더니 된다...
또, 과거에는 ProjectRepositoryCustom을 상속받으려면 ProjectRepositoryImpl이라고 했어야 했는데, 이제 ~CustomImpl도 가능하다.
결론
다음과 같이 명명을 해 주어야 한다.
- Custom하려는 Repo는 상속받을 Repository와 이름이 같아야 한다.
- 만약 CQS를 시행하고자 했으면 조회를 위한 Repository를 ProjectViewRepository로 따로 만들어 주어야 한다.
- 이제는 Custom Repo를 구현하는 Impl class에는 CustomImpl로 명명해 이름에 일관성이 있게 하자.
'DB > JPA' 카테고리의 다른 글
Join과 fetch join, 알고 쓰자. (0) | 2023.03.31 |
---|---|
왜 GenerationType.Identity를 써 주는 것일까? (0) | 2023.02.23 |