skip to Main Content

I developed a spring boot application, in the controller I have a method that returns a list of shops and one of the shop. I want to make different response for different get method, since when you use find all method, not all of the data is necessary, especially to avoid redundancy of data. But, when you use find by id method, you need all of the data with all the relation.

Below is my controller

@GetMapping
    public List<Shops> findAll(){
        return shopService.findAll();
    }

@GetMapping("/{id}")
    public Shops findById(@PathVariable("id") UUID id){
        return shopService.findOne(id);
    }

The result of find all method is as follows :

[
  {
    "created_at": "2023-02-16T02:28:31.545+00:00",
    "updated_at": "2023-02-16T02:28:31.545+00:00",
    "id": "d66cd6ff-8a22-4280-8b23-5d0a3ca01f93",
    "name": "Panda Star",
    "city": "Chicago",
    "purpose": "technology",
    "products": [
      {
        "created_at": "2023-02-16T02:28:31.563+00:00",
        "updated_at": "2023-02-16T02:28:31.563+00:00",
        "id": "e0b1a1cd-33b4-428b-b4f5-8885428d87eb",
        "name": "Logitech M510 Wireless",
        "description": "some desc"
      }
    ],
    "user": {
        "created_at": "2023-02-13T02:28:31.563+00:00",
        "updated_at": "2023-02-13T02:28:31.563+00:00",
        "id": "f58f8016-d9be-4c9d-b4e3-632a262ceca9",
        "name": "user1",
        "email": "[email protected]"
    }
  }
]

and for find by id:

{
  "created_at": "2023-02-16T02:28:31.545+00:00",
  "updated_at": "2023-02-16T02:28:31.545+00:00",
  "id": "d66cd6ff-8a22-4280-8b23-5d0a3ca01f93",
  "name": "string",
  "city": "string",
  "purpose": "string",
  "products": [
    {
      "created_at": "2023-02-16T02:28:31.563+00:00",
      "updated_at": "2023-02-16T02:28:31.563+00:00",
      "id": "e0b1a1cd-33b4-428b-b4f5-8885428d87eb",
      "name": "string",
      "description": "string"
    }
  ],
  "user": {
        "created_at": "2023-02-13T02:28:31.563+00:00",
        "updated_at": "2023-02-13T02:28:31.563+00:00",
        "id": "f58f8016-d9be-4c9d-b4e3-632a262ceca9",
        "name": "user1",
        "email": "[email protected]"
    }
}

How can I modify the method find all so that the result comes like this

[
  {
    "created_at": "2023-02-16T02:28:31.545+00:00",
    "id": "d66cd6ff-8a22-4280-8b23-5d0a3ca01f93",
    "name": "Panda Star",
    "city": "Chicago",
    "products": [
      {
        "id": "e0b1a1cd-33b4-428b-b4f5-8885428d87eb",
        "name": "Logitech M510 Wireless",
      }
    ]
  }
]

but, still keeping the find by id result as it is?

2

Answers


  1. you can do one of the samples:

    using DTO class that what you need:

    import lombok.Data;
    
    @Data
    class ShopsDto{
    
     Date created_at;
     String   id;
     String name;
     String   city;
     ProductDto products;
    }
    

    and convert your entity object to DTO object. for this work you can do it manually and using some library for that like mapstruct that It have integrated with lombok too.

    private ShopConverter converter;
    
    @GetMapping
    public List<ShopsDto> findAll(){
        return converter.toDto(shopService.findAll());
    }
    

    in another way you can use spring data Projection that Interface specify
    what fields you selected:

    class ShopsProduct{
    
     Date getCreated_at();
     String   getId();
     String getName();
     String   getCity();
     Product getProducts();
    }
    
    class ShopRepository extend JpaRepository<Shops>{
      List<ShopsProduct> findAll();
    }
    

    for better understanding you can see this link

    Login or Signup to reply.
  2. I would suggest using mapper in your service layer for your issue.

    Defining ShopVO which you want for view:

    public class ShopVO {
        private Date createdAt;
        private UUID id;
        private String name;
        private String city;
        private List<Product> products;
    
        // getters and setters, or @Data annotation
    }
    

    create ShopMapper for mapping Shop to ShopVO:

    @Component
    public class ShopMapper {
        
        @Autowired ModelMapper modelMapper;
    
        public List<ShopVO> toVO(List<Shop> shops){
            List<ShopVO> vos = new ArrayList<>();
            for(Shop shop : shops){
                vos.add(toVO(shop));
            }
            return vos;
        }
    
        public ShopVO toVO(Shop shop){
            return modelMapper.map(shop, ShopVO.class);
        }
    
    }
    

    In ShopService:

    @Override
    public List<ShopVO> findAll() {
        return shopMapper.toVO(shopRepo.findAll());
    }
    
    @Override
    public Shop findOne(UUID id) {
        return shopRepo.getReferenceById(id);
    }
    

    Hope it helps 🙂

    EDIT:

    Bean for ModelMapper:

    @Bean
    public ModelMapper modelMapper() {
      ModelMapper modelMapper = new ModelMapper();
      modelMapper.getConfiguration().setAmbiguityIgnored(true);
      return modelMapper;
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search