Spring - Advanced Comparator to Support QueryDsl

Following the official documentation , adding the @EnableSpringDataWebSupport annotation to my Spring configuration allows you to automatically enter the Predicate class in the request:

 @RequestMapping(method = RequestMethod.GET, path="/find") public ResponseEntity<PagedResources<FooResource>> find(Pageable pageable, PagedResourcesAssembler<Foo> assembler, @QuerydslPredicate(root = Foo.class) Predicate predicate) { Page<Foo> foos = fooRepository.findAll(predicate, pageable) final ResourceAssemblerSupport<Foo, FooResource> fooResourceAssembler = new ....; final PagedResources<FooResource> pagedResources = assembler.toResource(foos, fooResourceAssembler); return new ResponseEntity<>(pagedResources, HttpStatus.OK); } 

Then I can easily do a search when I execute a GET request:

 GET /foo/name?=bob&name=alice&age=20 

It works great. However, I was wondering how to achieve more advanced search criteria:

  • >
  • <
  • >=
  • <=

Normally I would like to apply these operators to numeric and date fields in my data models. This type of criterion is supported in Querydsl.

I tried adding > (%3E) to my query parameters, but it did not parse (for example, for a numeric field such as the age that it complains, it cannot parse >10 as a number.

Can this operator be used directly in a query?

(In case this is important, I use Spring Data Mongodb)

+5
source share
1 answer

DSL request custom binding - more than comparison

What you can do is define your own QueryDSL binding in your repository by expanding QueryDslPredicateExecutor and QuerydslBinderCustomizer :

 public interface FooRepository extends CrudRepository<Foo, Integer>, QueryDslPredicateExecutor<Foo>, QuerydslBinderCustomizer<QFoo> { default void customize(final QuerydslBindings bindings, final QFoo foo) { SingleValueBinding<NumberPath<Integer>, Integer> singleBinding = new SingleValueBinding<NumberPath<Integer>,Integer>(){ @Override public Predicate bind(NumberPath<Integer> path, Integer ageValue) { return path.gt(ageValue); } }; bindings.bind(foo.age).first(singleBinding); } } 

I am not an expert on DSL request, but I understand the following:

the binding determines how a particular field should be compared with its database column.

Same binding with java 8 lambda: (path, ageValue) -> path.gt(ageValue) . You should read the code in configuration mode in terms of the URL:

select Foos for which the age provided as a parameter is greater than the database value.

DSL request custom binding - between comparisons

Another option is to provide a lower and upper bound for your parameter, for example ?age=10&age=30 . Then define the following binding:

 default void customize(final QuerydslBindings bindings, final QFoo foo) { bindings.bind(foo.age).all((path, ageValue) -> { Iterator<? extends Long> it = value.iterator(); return path.between(it.next(), it.next()); }); } 
+1
source

All Articles