1

I am stuck on the pagination part for the interface based projection. So basically I am using an interface for the projection and building my custom response. This is the sample query

@Query(value = "SELECT course AS courseName, teacher as teacherName, student AS studentName FROM table WHERE id = ?1 AND created_date <= ?2 AND created_date >= ?3 ")
Page<CustomResult> getData(UUID id, LocalDateTime date, LocalDateTime date1, Pageable pageable);

And this my interface

public interface CustomResult {
    String getCourseName();
    String getTeacherName();
    String getStudentName();
}

I am able to achieve the pagination here and I am getting the desired result something like this

{
    "_embedded":  {
        "tupleBackedMaps": [
            {
                "courseName": "",
                "teacherName": "",
                "studentName": ""
            },
            {
                "courseName": "",
                "teacherName": "",
                "studentName": ""
            }
        ]
    },
    "_links": {},
    "page": {
        "size": 10,
        "totalElements": 2,
        "totalPage": 1,
        "number": 0
    }
}

But my problem here is little different I want to change the key name here tupleBackedMaps to somethingElse. And I also want to do the ordering of elements in the result. But I don't know how to do that with interface based projection.

If it was a class based projection I know there is something called RepresentationModel which can be used and @Relation and JsonOrder can be used to achieve what I want. But I don't know how to do this with interface.

Is there a way ? Please let me know if there is any other way or workaround ?

Lokesh Pandey
  • 1,739
  • 23
  • 50
  • You can use the `map()` function on `Page` to map from `CustomResult` to a `CustomResultDto` in your web layer. For the ordering, just add an order in your query. – Wim Deblauwe Jun 19 '23 at 13:48
  • @WimDeblauwe I am not sure of that, I just want to change the key name from `tupleBackedMaps` to `somethingElse` and don't want to touch my custom response. I will give it a try. Related to the ordering part I have already tried in the query and placed the way I want it still not helping it – Lokesh Pandey Jun 19 '23 at 14:29
  • If using native query is not a problem for you !! This worked for me https://stackoverflow.com/a/75623759/16769477 – Jay Yadav Jun 19 '23 at 15:02
  • @WimDeblauwe Can you help me figure this out ? I am not able to get this done using `map` – Lokesh Pandey Jun 23 '23 at 15:43
  • @LokeshPandey Do you have a sample github project that shows the problem? – Wim Deblauwe Jun 24 '23 at 12:34
  • @WimDeblauwe no, but the response is same as what I have shown as well as the query and interface data model – Lokesh Pandey Jun 24 '23 at 14:40
  • @WimDeblauwe can you look at my answer if that's what you were referring ? – Lokesh Pandey Jun 29 '23 at 16:23

1 Answers1

0

The solution seems bit inefficient to me. But other than this I couldn't figure out anything. Please let me know if you have came across solution better than this. I also don't understand since the springboot provides interface based data projection why didn't it provides these small stuffs at the interface level ? Probably this is for another debate.

So what I have done here is I have created a class say

@Data
@Builder
@Relation()
public class CustomResultResponse extends RepresentationModel<CustomResultResponse> {
    String courseName;
    String teacherName;
    String studentName;
}

And extracted the result from the pagination

List<CustomResult> customResult = result.getContent()

And then converted the list customResult to CustomResultResponse, something like this

//
List<CustomResult> customResult = result.getContent()
List<CustomResultResponse> formattedResponse = new ArrayList<>();
for(CustomResult custom : customResult) {
    CustomResultResponse response = CustomResultResponse.builder()
    .courseName(response.getCourseName())
    .teacherName(response.getTeacherName())
    .studentName(response.getStudentName())
    .build()
    formattedResponse.add(response);
}

And then converted the list to page and returned.

The problem is I don't see much issue here since the result I am getting from the database is paginated, so at max there won't be more than 20 results. This seems fine for the smaller page size but I am pretty sure this will be not be efficient if page size grows. Also I am not able to digest the idea of converting the response CustomResult to CustomResultResponse.

Lokesh Pandey
  • 1,739
  • 23
  • 50