문제
QueryDSL + Projections 사용 시 fetch join 오류
QueryDSL을 사용하여 Todo 엔티티를 조회하면서 Todo.managers 컬렉션을 fetch join으로 함께 가져오고, 결과를 DTO로 매핑하기 위해 Projections.constructor()를 사용했다.
실행 시 아래와 같은 예외가 발생했다.
jakarta.servlet.ServletException: Request processing failed: java.lang.IllegalArgumentException: org.hibernate.query.SemanticException: Query specified join fetching, but the owner of the fetched association was not present in the select list [SqmListJoin(org.example.expert.domain.todo.entity.Todo(todo).managers(manager))]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1022) ~[spring-webmvc-6.1.12.jar:6.1.12]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903) ~[spring-webmvc-6.1.12.jar:6.1.12]
List<TodoSearchResponse> todos = queryFactory
.select(Projections.constructor(TodoSearchResponse.class,
todo.title,
manager.countDistinct(),
comment.countDistinct())) // manager, comment의 조인으로 인해 데이터 중복 발생 가능 -> countDistinct() 사용
.from(todo)
.leftJoin(todo.managers, manager)
.leftJoin(todo.comments, comment)
.where(
StringUtils.isBlank(title) ? null : todo.title.like(title),
StringUtils.isBlank(nickname) ? null : todo.user.nickname.like(nickname),
createdFrom == null ? null : todo.createdAt.after(createdFrom.atStartOfDay()),
createdTo == null ? null : todo.createdAt.before(createdTo.atTime(23, 59, 59))
)
.offset((long) (page - 1) * size)
.limit(size)
.orderBy(todo.createdAt.desc())
.groupBy(todo) // 특정 할 일에 대해 manager, comment 조회
.fetch();
원인 분석 및 해결
https://go-getter1kim.tistory.com/146
QueryDSL Projections (JPAExpressions을 사용해서 조인 문제 해결)
Projection없이 QueryDSL을 사용해서 데이터를 조회하는 경우에는 Todo 엔티티 자체를 select하는 QueryDSL 로직을 만들어엔티티에 포함된 다른 엔티티를 모두 fetch join 해야 한다.그리고 가져온 Todo에서 필
go-getter1kim.tistory.com
문제
error : Method 'insertUserData' annotated with '@BeforeAll' should be static
테스트 코드 중 insertUserData 메서드가 @BeforeAll 어노테이션과 함께 사용되려면 static 메서드로 선언해야 한다.
원인 분석
@BeforeAll은 해당 테스트 클래스를 실행하기 전에 한 번만 수행되도록 하는 어노테이션이다.
JUnit은 테스트 클래스의 객체를 생성하기 전에 이 메서드를 실행하려고 한다.
하지만 일반 메서드는 객체가 생성되어야만 호출할 수 있으므로, static이어야 객체 없이 호출 가능하다.
하지만 해당 메서드를 static으로 변경하면 @Autowired로 Repository를 주입받을 수 없다.
static 메서드에 아직 생성되지 않은 객체가 접근할 수 없기 때문이다.
해결
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@TestInstance 어노테이션을 사용하면 @BeforeAll을 static으로 만들지 않아도 되도록 허용한다.
이 설정을 하면 JUnit이 테스트 클래스의 인스턴스를 한 번만 생성해서 사용하기 때문이다.
'Troubleshooting' 카테고리의 다른 글
대기열 구현 중 발생한 트러블슈팅 (0) | 2025.05.23 |
---|---|
@CreateBy 사용 시, 화이트리스트 요청될 때 유저 정보 null 처리 (0) | 2025.05.13 |
리스트 타입 필드는 @NotBlank 대신 @NotEmpty (2) | 2025.04.14 |
직렬화 실패 이슈 해결 (0) | 2025.04.10 |
[Java/Spring] Spring Data JPA 메서드명 설정, JPQL 사용 (0) | 2025.04.08 |