Rahul Bhooteshwar
Rahul Bhooteshwar

Reputation: 1955

Spring Data JPA exclude properties for specific RequestMapping

Considering the classic example of PetClinic Res API, I am having 2 REST calls:

First call returns all owners (detailed) and second return specific owner details.

In both the cases, each owner object contains the owner basic details along with list of pets and each pet further contains visits

What should be the best approach if I want to return owner list without pets and visit details for my findAll (first API) call and complete details for 2nd call??

I have explored custom serializer implementation but I don't want to apply that on Entity level. If I prepare JSON manually using jackson it will still make db calls!! I basically want to avoid unnecessary DB fetch in case of first REST call

Upvotes: 1

Views: 1558

Answers (2)

Deltharis
Deltharis

Reputation: 2373

You need to separate the database object from what you return then. Since pets are behind a LAZY OneToMany association, they will not get fetched the moment you get the list in findAll... But they will fetched when you pass your entity object into serailizing library that will (presumably) call every getter of the object given.

So now either you somehow modify serialization process so that it doesn't invoke wrong getters and trigger the fetch... or you make a mapper that turns entity into DTOs with only needed fields, and serialize them. There are existing mapping libraries you can use to ease that process (i.e. mapstruct).

You could even make those DTOs a proper part of your application as the API model - separating front facing API from database so that you can easier do cosmetic changes to it (fields you don't store in database, renames that don't break your JPQLs, generated documentation perhaps)

Upvotes: 1

Ngọc Hy
Ngọc Hy

Reputation: 300

I think what you need is returning Object instead of the exact Owner entity if you really want to do this. And if you want the DB layer to be efficient too, which is only fetch the properties that you need, you should create a function that takes a List contains values are the properties you need and that function would return an Object an then send it with your API. So in your case, it would be something like this.

//DAO 
public List<Object> findAll(List<String> fieldsNeeded) {
     String hql = "SELECT ";

     for (String field: fieldsNeeded) {
         hql += field + " ";
     }

     hql += "FROM //your table name";

     // create query and all those stuff;
     // return the result
}

//controller
@GetMapping("/petclinic/owners")
public List<Object> getOwners(//your parameters) {
     // (lets skip service layer)
     // then you need to prepare the list of needed properties
     // including checking if the properties do exsit in the table etc...
     // which also returns an object;

     List<String> fieldsNeeded = new ArrayList<String>();

     // add all the fieldnames;

     return ownerDao.findAll(fieldsNeeded);
}

Furthermore, if you have a huge table with tons of properties, you should change that "hql += ..." with the .append() function in the StringBuilder and if the amount of properties needed is too large, you should instead tell the function not to fetch the properties passed through but the un-passed ones.


So i just find out that you actually can not return an Object with REST. So in case you need to send jsut one Object, what i would suggest doing was adding an inject step in the Service layer after you had the result from the DAO layer, you set all the fields in the Object into the Entity and it should work fine.

Upvotes: 0

Related Questions