Home > other >  How to manipulate Optional Spring @RequestParam
How to manipulate Optional Spring @RequestParam

Time:12-24

I'm new to JPA. I have a class like this

@Table(name="student")
@Entity
public class Student{
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int studentId;
    
    @Column
    @Size(max = 20)
    private String name;
    
    @Column
    @Min(value = 2014)
    @Max(value = 2020)
    private int yearOfBirth;
    
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "classroomId")
    Classroom classroom;

    //Getters and setters
    }

My repository:

        @Repository
        public interface HocSinhRepository extends JpaRepository<Student, Integer> {}

My controller:

public class StudentController {
        @Autowired
        StudentRepository studentRepository;
        
        @GetMapping(value = "/get")
        public Page<Student> get(@RequestParam Optional<Integer> page, @RequestParam Optional<String> sortBy) {
            return studentRepository.findAll(
                    PageRequest.of(page.orElse(0), 3, Sort.Direction.ASC, sortBy.orElse("name"))
                    );
        }
    }

By using Optional.orElse, I can assign a default value to the sortBy parameter if it's null. How can I do the same thing if the parameter is not null, but just a non-sensible string (like "asdasd")?

CodePudding user response:

You can use the map operator of optionals.

So it would be

sortBy.map(o -> {
           if (o.equalsIgnoreCase("asdasd")){
               return "name";
           } else {
               return o;
           }
       }).orElse("name"));

This will make the optional return the value "name" when it is empty or when the containing value exists and is with ignore case "asdasd". In every other case it will return the original value it contained.

So your code will be adapted to be

return studentRepository.findAll(
                    PageRequest.of(page.orElse(0), 3, Sort.Direction.ASC, 
                                   sortBy.map(o -> {
                                              if (o.equalsIgnoreCase("asdasd")){
                                                   return "name";
                                              } else {
                                                   return o;
                                              }}).orElse("name"));
                   ));

CodePudding user response:

A common scenario would be:

To have the "valid field names" stored in a "data structure", e.g., like:

public static final Set<String> VALID_SORT_FIELDS = Set.of("name", "studentId"/*, all we "consider valid"...*/);

Then we can use it in our controller like:

@GetMapping(value = "/get")
public Page<Student> get(@RequestParam Optional<Integer> page, @RequestParam Optional<String> sortBy) {
  final String sort = sortBy
  .map( s -> 
      s != null && VALID_SORT_FIELDS.contains(s)?
          s : "name" // or a consatant com.domain.my...DEFAULT_SORT
  )
  .get();
  return studentRepository.findAll(
     PageRequest.of(page.orElse(0), 3, Sort.Direction.ASC, sort)
  );
}

When we want to ignore the case, we would adjust to:

...&&  VALID_SORT_FIELDS.contains(s.toLowerCase(/*some (default) Locale*/))

Another/additional possible approach: validaion-api... but the wrapping Optional is a "challange"(??)...

  • Related