I use native query and then I i do dto projections most of the time.
Here is an example of DTO projection
public interface OvertimeRequestView {
public Long getId();
public String getEmployeeFirstName();
public String getEmployeeLastName();
public Long getOvertimeHours();
public Date getOvertimeDate();
public String getDescription();
public String getStatus();
public String getApproverName();
public default String getEmployeeFullName() {
String lastName = this.getEmployeeLastName();
String firstName = this.getEmployeeFirstName();
if (null != firstName) {
return firstName.concat(" ").concat(lastName);
}
return lastName;
}
}
and here is the repository with a native query. notice that since the query returns 'id' column I have a getId() method in the dto above,and since it has employeeFirstName i have getEmployeeFirstName() in the dto and so on. Notice also that I include a count query, without a count query, the queries sometime fail especially if the queries are complex and contain joins
@Query(value = "select ovr.id,\n" +
" u.first_name as employeeFirstName,\n" +
" u.last_name as employeeLastName,\n" +
" ovr.overtime_date as overtimeDate,\n" +
" ovr.description as description,\n" +
" ovr.overtime_hours as overtimeHours\n" +
"from overtime_requests ovr\n" +
" left join employees e on ovr.employee_id = e.id\n" +
" left join users u on e.user_id = u.id",
nativeQuery = true,
countQuery = "select count(ovr.id)\n" +
"from overtime_requests ovr\n" +
" left join employees e on ovr.employee_id = e.id\n" +
" left join users u on e.user_id = u.id")
public Page<OvertimeRequestView> getAllActive(Pageable pageable);
For more you can check from spring data documentation