Search code examples
javasqlspringhql

org.springframework.core.convert.ConversionFailedException: Failed to convert from type


I am trying to get data from table in the StudentRepository :

 @Query("SELECT S.studentId, S.studentName, S.studentSurname, S.studentAge, S.entryYear," +
        "S.graduateYear, S.facultyName, G.groupName FROM Student S LEFT JOIN Group G ON G.groupId=G.groupId ORDER BY S.studentId")
    List<StudentDTO> getAllStudentDtos();

And when I launch program and try to get this data from controller :

  @GetMapping("students")
public String showStudents(Model model) {
    List<StudentDTO> students = studentService.getAllStudentDtos();
    model.addAttribute("students", students);
    return "studentViews/studentsPage";
} 

I gain this error.

Here all exception :

org.springframework.core.convert.ConversionFailedException: Failed to convert from type
[java.lang.Object[]] to type [@org.springframework.data.jpa.repository.Query
com.foxminded.university.dto.StudentDTO] for value '{1, Alexandr, Platonchik, 37, 1999, 2004, journalism, BIKS}'; nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.Integer] to type [@org.springframework.data.jpa.repository.Query com.foxminded.university.dto.StudentDTO]

Solution

  • This error happens because your method getAllStudentDtos in the repository returns a list of Student and not a List<StudentDTO> as you thought. Spring repositories are binded to an @Entity, in your case Student, so when you use the method return as List<Student> the problem occur.

    There are two possible solutions to your problem. The first is declare a construtor in your StudentDTO class with the exact field params you wanted for the query and use it in your getAllStudentDtos.

    eg:

    public StudentDTO(Long studentId, String studentName) {
        this.studentId = studentId;
        this.studentName = studentName;
    }
    

    ...

    @Query("SELECT new StudentDTO(S.studentId, S.studentName) FROM Student S LEFT JOIN Group G ON G.groupId=G.groupId ORDER BY S.studentId")
    List<StudentDTO> getAllStudentDtos();
    

    Note that I used only two fields in the example.

    Or you can implement a method in StudentDTO that transforms a Student entity to a StudentDTO and then map the list using your method.

    eg:

    List<StudentDTO> students = studentService.getAllStudentDtos().stream().map(student -> StudentDTO.toDto(student)).collect(Collectors.toList());