Home > OS >  How to add dynamic search by request param
How to add dynamic search by request param

Time:08-30

How should I correctly implement dynamic searching in my rest api request? My rest api is divided into Controller -> Service -> Repository. I created GET request to get all drivers from database:

@GetMapping
public ResponseEntity<Set<DriverDTO>> getAll(@PageableDefault(value = 15) Pageable pageable) {

    Page<DriverEntity> driverEntities = driverService.getAll(pageable);
    Set<DriverDTO> driverDTOSet = modelMapperService.mapPageToSetOfEnteredClass(driverEntities, DriverDTO.class);
    return new ResponseEntity<>(driverDTOSet, HttpStatus.OK);
}

and now I would like to add some searching parameters for example name, ageUpToX... so I added @RequestParams:

@GetMapping
public ResponseEntity<Set<DriverDTO>> getAll(@PageableDefault(value = 15) Pageable pageable,
                                             @RequestParam String name,
                                             @RequestParam int ageUpTo,
                                             @RequestParam int ageOver) {
    Page<DriverEntity> driverEntities = driverService.getAll(pageable);
    Set<DriverDTO> driverDTOSet = modelMapperService.mapPageToSetOfEnteredClass(driverEntities, DriverDTO.class);
    return new ResponseEntity<>(driverDTOSet, HttpStatus.OK);
}

Method getAll() from service looks like:

public Page<DriverEntity> getAll(Pageable pageable) {
    return driverEntityRepository.findAll(pageable);
}

So what is next? Should I add every requestParam to getAll method like: getAll(String name, int ageUpTo,int ageOver) and checking in few if loops if field is empty/ != null? Or maybe by some switch?

CodePudding user response:

If you want to validate query parameters, you don't have to use if statement, that can be done in a more elegant way using annotations.

First, you will need to include following dependency in your pom.xml file

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

The spring-boot-starter-validation dependency will include all the jars needed for the validation of the request parameters.

So, if you want to validate the query parameter ageUpTo has minimum value 5, and maximum value of 7 you can use @Validated annotation with @Min and @Max annotation. The @Validated annotation is used to specify the rest controller to be validated. The spring boot application validates all the method before it is called. Here is example:

@Validated
 public RestController {

       @GetMapping
        public ResponseEntity<Set<DriverDTO>> getAll(@PageableDefault(value = 15) Pageable pageable,
                                                     @RequestParam String name,
                                                     @RequestParam @Min(5) @Max(7) int ageUpTo,
                                                     @RequestParam int ageOver) {
            Page<DriverEntity> driverEntities = driverService.getAll(pageable);
            Set<DriverDTO> driverDTOSet = modelMapperService.mapPageToSetOfEnteredClass(driverEntities, DriverDTO.class);
        return new ResponseEntity<>(driverDTOSet, HttpStatus.OK);
    }

}

If you want to validate that your request param name is not blank, you can use @NotBlank annotation.

Also, you can customize the messages that will be displayed to the user in case the validation fails.

You can read more about it here or here

If you want to search the database based on the given query parameters, you will have to declare a new method in the repository interface, which will perform the search based on the given parameters. This implies that you will also have to declare a new method in the service that will call that method, similar to what you did earlier.

CodePudding user response:

i think you need to add those parameters to your service method, otherwise to do is instead of sending one by one, you could send a Map to the service, where the key would be the column you need to filter, then you can iterate over the map and if the key/value are not null you can add this to a query Specification e.g:

Specification<MyDomain> querySpec = Specifications.where((root, query, cb) -> {
     Predicate p = null;
     //iterate over the map
     mapParam.forEach(k,v -> {
       if(k != null && v!= null) {
          p = cb.and(p, cb.equal(root.get(k), k));
       }
     })
     return p;
                });

// then use the specification
Page<MyDomain> pageResult = myRepo.findAll(querySpec, pageRequest);

beware that you need to perform some validations cuz p may be null, another important thing is that your repository must extend from JpaSpecificationExecutor

  • Related