본문 바로가기

Spring

JPA ConverterNotFoundException: No converter found capable of converting from type 에러 해결

ConverterNotFoundException: No converter found capable of converting from type

문제 상황

@Query(nativeQuery = true,
        value = "SELECT s.id, s.email, s.name " +
        "FROM student s " +
        "LEFT OUTER JOIN team t ON s.team_id = t.id " +
        "WHERE now() BETWEEN t.start_date AND t.end_date " +
        "AND t.category_id IN :categoryList " +
        "AND t.is_public = :isPublic")
List<StudentDto> find(@Param("categoryList") List<Long> categoryList,
                      @Param("isPublic") Flag isPublic);

nativeQuery를 true로 놓고 쿼리를 날린 후 Dto로 받아오려고 했다.

쿼리를 날린 결과가 DTO에 매핑되지 않아서 즉, 결과를 객체로 변환하는 데에 실패해서 발생한 에러.

 

해결 및 개선

구글링을 통해 찾아본 해결 방법으로는 기존의 WrapperClass를 내가 필요한 것만 있는 interface로 정의하는 방법이 있었다.

public interface StudentDtoInterface {

	Long getId();
    
	String getName();
    
}

위는 예시 코드다.

나의 경우엔 실제로는 Dto에 넣어야할 데이터의 개수가 훨씬 많았고, 이런 식으로 인터페이스로 만들어서 하는 게 맞는지에 대해 의문이 들었다.

 

그래서 JPA를 사용한 다른 코드들의 로직을 생각해봤다.

JpaRepository에서 제공해주는 findAll()을 호출해서 List<Student>를 받아온 뒤,

서비스 계층에서 필요한 정보만 가져다가 Dto로 변환해서 응답으로 반환하는 형식으로 구현했다.

이 부분도 마찬가지로 우선 List<Student>를 받아온 다음에 서비스 계층에서 Dto로 변환하기로 했다.

 

@Query(value = "SELECT s " +
        "FROM Student s " +
        "LEFT JOIN s.team t " +
        "WHERE current_timestamp BETWEEN t.startDate AND t.endDate " +
        "AND t.category_id IN :category_id " +
        "AND t.is_public = :isPublic")
List<Student> find(@Param("categoryList") List<Long> categoryList,
                   @Param("isPublic") Flag isPublic);

nativeQuery를 사용하지 않았다.

Repository에서는 이렇게 List<Student>로 받아온 뒤

서비스 계층에서 Dto로 변환해서 필요한 정보만 응답할 수 있도록 했다.

이렇게 하는 것이 다른 인터페이스를 추가하고 하는 것보다 더 JPA스럽다..?고 생각한다.

 

개인적으로는 꼭 필요한 상황이 아닌 이상 전자처럼 DTO로 바로 받아오는 방식으로 구현하려면

JPA, JPQL이 아니라 MyBatis로 개발하는 것이 더 좋아보인다.

 

이 글의 코드를 보다가 저 파라미터들을 한 번에 넘기고 싶다는 생각이 들었다면 아래 글을 봐주세요~

https://33233.tistory.com/6

 

 

참고

https://algorithmstudy-mju.tistory.com/153