Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Data Query Method with Optional @Param

Is it possible to allow query method @Params to be optional, specifically in the case of Spring Data REST?

For example, I'd like to bind a very similar search to the same resource path. To do this now, I would need something like the following:

@RestResource(path = "driver", rel = "byDriver")
List<Bar> findByDriverId(@Param("id") String id, Pageable pageable);

@RestResource(path = "driverAndSpan", rel = "byDriverAndSpan")
List<Bar> findByDriverIdAndStartTimeGreaterThanEqualAndEndTimeLessThanEqual(@Param("id") String id, @Param("start") Date start,
        @Param("end") Date end, Pageable pageable);

Which gives me:

byDriver: {
  href: "http://localhost:8080/foo/search/driver{?id,page,size,sort}",
},
byDriverAndSpan: {
  href: "http://localhost:8080/foo/search/driverAndSpan{?id,start,end,page,size,sort}",
}

What I want is to be able to see something like the following path, where start and end are optional parameters, rather than defining multiple methods in my Repository.

byDriverAndSpan: {
  href: "http://localhost:8080/foo/search/driverAndSpan{?id,*start,*end,page,size,sort}",
}

Which could potentially look like:

@RestResource(path = "driverAndSpan", rel = "byDriverAndSpan")
List<Bar> findByDriverIdAndStartTimeGreaterThanEqualAndEndTimeLessThanEqual(@Param("id") String id, @Param(value = "start", optional = true) Date start,
        @Param(value = "end", optional = true) Date end, Pageable pageable);
like image 734
bvulaj Avatar asked Sep 10 '14 19:09

bvulaj


People also ask

How do I add optional parameters in spring boot?

You can do it in three ways: Set required = false in @RequestParam annotation. Set defaultValue = “any default value” in @RequestParam annotation. Using Optional keyword.

What is difference between CrudRepository and JpaRepository?

CrudRepository mainly provides CRUD operations. PagingAndSortingRepository provide methods to perform pagination and sorting of records. JpaRepository provides JPA related methods such as flushing the persistence context and deleting of records in batch.

What is optional findById?

Its findById method retrieves an entity by its id. The return value is Optional<T> . Optional<T> is a container object which may or may not contain a non-null value. If a value is present, isPresent returns true and get returns the value.

How does JPA handle null values?

The JPA specification defines that during ordering, NULL values shall be handled in the same way as determined by the SQL standard. The standard specifies that all null values shall be returned before or after all non-null values. It's up to the database to pick one of the two options.


1 Answers

Maybe you can define a 'main' function as default which will delegate to the other functions. Something like this

@RestResource(path = "driverAndSpan", rel = "byDriverAndSpan")
default List<Bar> findByDriverIdAndOptionalStartTimeGreaterThanEqualAndOptionalEndTimeLessThanEqual(@Param("id") String id, @Param(value = "start", optional = true) Date start,
        @Param(value = "end", optional = true) Date end, Pageable pageable) {
   if(start != null && end != null) {
      return findByDriverIdAndStartTimeGreaterThanEqualAndEndTimeLessThanEqual(id, start, end, pageable);
   }
   return findByDriverId(id, pageable);
}

I think you can even use Optional as a parameter type, then you can use function overloading

@RestResource(path = "driverAndSpan", rel = "byDriverAndSpan")
default List<Bar> findByDriverIdAndStartTimeGreaterThanEqualAndEndTimeLessThanEqual(
@Param("id") String id, @Param(value = "start") Optional<Date> start,
        @Param(value = "end") Optional<Date> end, Pageable pageable) {
   if (!start.isEmpty() && !end.isEmpty()) {
      return findByDriverIdAndStartTimeGreaterThanEqualAndEndTimeLessThanEqual(id, start.get(), end.get(), pageable);
   }
   return findByDriverId(id, pageable);
}

List<Bar> findByDriverIdAndStartTimeGreaterThanEqualAndEndTimeLessThanEqual(String id, Date start, Date end, Pageable pageable);

Notice that in this case, you shouldn't expose the other endpoints, and only expose this default method.

like image 164
Ahmed Sayed Avatar answered Oct 06 '22 00:10

Ahmed Sayed