[JPA] No constructor found for class 에러

개발자 P군·2024년 5월 27일
post-thumbnail

❗ 문제발생

  • 사이드 프로젝트 진행중 JPA에서 Projection.constructor을 사용할 때해당 에러가 발생했다. 해당 원인을 찾아보니 Dto.class에서 정의하는 필드와 Repository에서 select로 표현하고자하는 필드가 완전히 일치하지 않아서 발생하는 문제라고 한다!

💡 해결방안

  1. 모든 필드의 타입이 일치해야 한다.
  2. 모든 필드의 순서가 일치해야 한다.
  3. Repository와 DTO의 필드명이 다르다면 .as("별칭") 메서드를 사용해서 Dto 쪽에서의 필드명과 같도록 별칭을 지정해주도록 한다.

예시코드

  • DTO 클래스
@Getter
@AllArgsConstructor
public class UserDto {
    private String name;      // 필드명 'name'
    private Integer age;      // 필드명 'age'
}
  • Repository 코드
public List<UserDto> findUsers() {
    QUser user = QUser.user;

    return queryFactory
            .select(Projections.constructor(UserDto.class, 
                    user.username,  // DTO의 필드명과 다름 (name 대신 username)
                    user.age
            ))
            .from(user)
            .fetch();
}
  • 위 코드는 DTO의 필드명 name과 Repository의 select 구문에서 사용된 user.username이 일치하지 않기 때문에 에러가 발생한다.

해결 코드

해결 방법은 .as("별칭")을 사용하여 DTO의 필드명과 Repository의 필드명을 맞추는 것이다.

  • 수정된 Repository 코드
public List<UserDto> findUsers() {
    QUser user = QUser.user;

    return queryFactory
            .select(Projections.constructor(UserDto.class, 
                    user.username.as("name"), // 필드명을 DTO에 맞게 별칭 설정
                    user.age
            ))
            .from(user)
            .fetch();
}
  • 위 코드에서 .as("name")을 추가해 user.username을 name으로 매핑함으로써 에러를 해결할 수 있다.

🔍 정리

  • DTO와 select 쿼리의 필드명이 다르면 .as("별칭")으로 필드명을 맞춰준다.
  • 필드의 순서와 타입도 반드시 일치해야 한다.
  • 이러한 규칙들을 준수하면 Projections.constructor를 활용한 Projection을 제대로 사용할 수 있다.
profile
문제를 발견하고 해결하는 과정을 통해 얻은 새로운 지식을 공유하고자 합니다.

0개의 댓글