java - Spring - 支持 QueryDsl 的高级比较器

标签 java spring spring-boot spring-data querydsl

official documentation 之后, 添加 @EnableSpringDataWebSupport我的 Spring 配置注释允许自动注入(inject) 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)

最佳答案

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

您可以通过扩展 QueryDslPredicateExecutorQuerydslBinderCustomizer 在您的存储库中定义您自己的 QueryDSL 绑定(bind):

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

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

a binding defines how a specific field is to be compared to its database column.

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

fetch the Foos for which the age provided as parameter is greater than the database's value.

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

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

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

关于java - Spring - 支持 QueryDsl 的高级比较器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39039346/

相关文章:

java - 如何仅重新运行失败的测试? (我用的是junit5+maven+spring boot)

java - 处理慢速消费者 kafka 上的背压并避免重新平衡

java - 解析: Unauthorized when querying ParseInstallation

java - c3p0 网络中断后重新连接

javascript - 如何将一个网址重定向到另一个网址?

java - 使用自定义用户对象时的 Spring session redis

java - 使用 Jackson 序列化对象时如何覆盖类型信息?

java - 将 JMenuBar 添加到 JFrame

java - 如何为 @Async 方法使用自定义执行器?

java - UnsatisfiedDependencyException 在构造函数上 Autowiring 并且设置不起作用