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.Date
instead 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: