简体   繁体   English

Spring-支持QueryDsl的高级比较器

[英]Spring - Advanced comparator for QueryDsl support

Following the official documentation , adding @EnableSpringDataWebSupport annotation to my Spring configuration allows to automatically inject a Predicate class in query: 遵循官方文档 ,在我的Spring配置中添加@EnableSpringDataWebSupport批注允许在查询中自动注入Predicate类:

@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 search when performing the GET request: 然后,我可以在执行GET请求时轻松搜索:

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

This works fine. 这很好。 However I was wondering how to achieve more advanced search criteria: 但是我想知道如何实现更高级的搜索条件:

  • >
  • <
  • >=
  • <=

Typically I would like to apply these operators to numeric and date fields in my data models. 通常,我想将这些运算符应用于数据模型中的数字和日期字段。 These sorts of criterion are supported in Querydsl. Querydsl支持这些类型的条件。

I tried adding > (%3E) in my query parameters but it fails parsing (for example for numeric field like age it complains it cannot parse >10 as a number. 我尝试在查询参数中添加> (%3E) ,但解析失败(例如,对于年龄这样的数字字段,它抱怨无法将>10解析为数字。

Is it possible to use this operator directly in the query? 是否可以在查询中直接使用此运算符?

(In case it matters I'm using Spring Data Mongodb) (以防万一,我正在使用Spring Data Mongodb)

Custom Query DSL binding - greater than comparison 自定义查询DSL绑定-大于比较

What you can do is define your own QueryDSL Binding in your repository, by extending QueryDslPredicateExecutor and QuerydslBinderCustomizer : 您可以做的是通过扩展QueryDslPredicateExecutorQuerydslBinderCustomizer在存储库中定义自己的QueryDSL绑定:

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'm no Query DSL expert, but my understanding is the following: 我不是Query DSL专家,但是我的理解是:

a binding defines how a specific field is to be compared to its database column. 绑定定义如何将特定字段与其数据库列进行比较。

The same binding with java 8 lambda: (path, ageValue) -> path.gt(ageValue) . 与Java 8 lambda相同的绑定: (path, ageValue) -> path.gt(ageValue) You have to read the code in customize method from the url parameter's perspective: 您必须从url参数的角度阅读customize方法中的代码:

fetch the Foos for which the age provided as parameter is greater than the database's value. 获取其参数作为参数提供的年龄大于数据库值的Foos。

Custom Query DSL binding - between comparison 自定义查询DSL绑定-比较之间

Another option is to provide lower and upper bound for your parameter, like this: ?age=10&age=30 . 另一个选择是为您的参数提供上下限,例如: ?age=10&age=30 Then, define the following binding: 然后,定义以下绑定:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM