Spring - 支持QueryDsl的高级比较器

问题描述 投票:6回答:1

official documentation之后,在我的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);
}

然后我可以在执行GET请求时轻松搜索:

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

这很好用。但是我想知道如何实现更高级的搜索条件:

  • >
  • <
  • >=
  • <=

通常,我想将这些运算符应用于数据模型中的数字和日期字段。 Querydsl支持这些标准。

我尝试在我的查询参数中添加> (%3E),但它无法解析(例如,对于数字字段,如年龄,它抱怨它不能解析>10作为数字。

是否可以在查询中直接使用此运算符?

(如果重要的话我正在使用Spring Data Mongodb)

java spring spring-boot spring-data querydsl
1个回答
2
投票

自定义查询DSL绑定 - 大于比较

您可以做的是通过扩展QueryDslPredicateExecutorQuerydslBinderCustomizer在您的存储库中定义您自己的QueryDSL Binding:

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);
    }
}

我不是查询DSL专家,但我的理解如下:

绑定定义如何将特定字段与其数据库列进行比较。

与java 8 lambda相同的绑定:(path, ageValue) -> path.gt(ageValue)。您必须从url参数的角度阅读customize方法中的代码:

获取作为参数提供的年龄大于数据库值的Foos。

自定义查询DSL绑定 - 比较之间

另一种选择是为参数提供下限和上限,如下所示:?age=10&age=30。然后,定义以下绑定:

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());
    });
}
© www.soinside.com 2019 - 2024. All rights reserved.