The error that I gained in my repository :
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: Unable to locate appropriate constructor on class [com.foxminded.university.dto.LessonDTO]. Expected arguments are: int, java.lang.String, int, java.util.Date, java.lang.String, java.lang.String [ SELECT NEW LessonDTO (L.lessonId, L.lessonName, L.classNumber, L.date, T.teacherName, G.groupName) FROM com.foxminded.university.model.Lesson L LEFT JOIN com.foxminded.university.model.Teacher T ON L.teacherId = T.teacherId LEFT JOIN com.foxminded.university.model.Group G ON L.groupId=G.groupId ORDER BY L.lessonId]
The query where I have the error :
@Query(" SELECT NEW LessonDTO (L.lessonId, L.lessonName, L.classNumber, L.date, T.teacherName, " +
"G.groupName) FROM Lesson L LEFT JOIN Teacher T ON L.teacherId = T.teacherId LEFT JOIN Group G ON " +
"L.groupId=G.groupId ORDER BY L.lessonId")
List<LessonDTO> getAllLessonDtos();
Class LessonDTO :
@ToString
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Entity
public class LessonDTO {
@Id
private int id;
private String name;
private intclassNumber;
private Date date;
private String teacherName;
private String groupName;
}
Lesson.class :
@Entity
@ToString
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class Lesson {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer lessonId;
private String lessonName;
private Integer classNumber;
private Timestamp date;
private Integer teacherId;
private Integer groupId;
public Lesson(String lessonName, Integer classNumber, Timestamp date, Integer teacherId, Integer groupId) {
this.lessonName = lessonName;
this.classNumber = classNumber;
this.date = date;
this.teacherId = teacherId;
this.groupId = groupId;
}
}
Group.class :
@Entity
@ToString
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "groups", schema = "public")
public class Group {
@Id
@Column(name="group_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)|
private Integer groupId;
@Column(name="group_name")
private String groupName;
}
Teacher.class :
@Entity
@ToString
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "teachers", schema = "public")
public class Teacher {
@Id
@Column(name="teacher_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer teacherId;
@Column(name = "teacher_name")
private String teacherName;
@Column(name = "position")
private String position;
public Teacher(String teacherName, String position) {
this.teacherName = teacherName;
this.position = position;
}
}
Similiar method in this application for StudentDTO works fine :
@Query("SELECT NEW StudentDTO (S.studentId, S.studentName, S.studentSurname, S.studentAge, S.entryYear," +
"S.graduateYear, S.facultyName, G.groupName) FROM Student S LEFT JOIN Group G ON S.groupId=G.groupId ORDER BY S.studentId")
List getAllStudentDtos();
If you need some more information for helping, write, please. Thanks in advance!
The workaround (adding a constructor with
java.util.Dateinstead ofjava.sql.Timestamp) is not portable and (most important) not at all intuitive.Moreover, if its Entity DTO then cant assign any field not matching with DB fieldType.. have to write separate pojo - not worthy
If you have a (SQL) Timestamp in a query, you expect it to be assignable to a
java.sql.Timestamp. Timestamp can have precision up to the nanosecond, which is not the case for Date. Use constructor as below and cast the Object: