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!

1

There are 1 answers

0
Jags On

The workaround (adding a constructor with java.util.Date instead of java.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:

public sampleDto(String name, Object lastUpdated) {
  this.name = name;
  this.lastUpdated = (Timestamp) lastUpdated;
}