Spring - QueryDsl 支持的高级比较器
Posted
技术标签:
【中文标题】Spring - QueryDsl 支持的高级比较器【英文标题】:Spring - Advanced comparator for QueryDsl support 【发布时间】:2016-12-26 15:11:12 【问题描述】:在official documentation 之后,将@EnableSpringDataWebSupport
注释添加到我的Spring 配置允许在查询中自动注入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)
【问题讨论】:
你有没有找到实现这个的方法?我一直在尝试实现类似的东西,但没有成功。 @woemler 我实际上已经暂时搁置了这个问题,但它并没有消失。我想我最终会编写自己的代码来解析查询参数。我需要检查是否有一种简单的方法可以将其与弹簧注射机构集成。当我开始这样做时,我可能会在 spring github 存储库上寻求建议。如果我发现一些有趣的东西,会在这里写下来作为答案 @phoenix7360 有什么事吗?我也想这样做,但仍然使用@QuerydslPredicate
@StopHarmingMonica 不幸的是我从来没有做到这一点,只是放弃了:/
@phoenix7360 Spring Data Querydsl 值运算符库执行此操作...
【参考方案1】:
自定义查询 DSL 绑定 - 大于比较
您可以通过扩展QueryDslPredicateExecutor
和QuerydslBinderCustomizer
在存储库中定义自己的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);
我不是 Query DSL 专家,但我的理解如下:
绑定定义如何将特定字段与其进行比较 数据库列。
与 java 8 lambda 相同的绑定:(path, ageValue) -> path.gt(ageValue)
。您必须从 url 参数的角度阅读自定义方法中的代码:
获取作为参数提供的年龄大于的 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());
);
【讨论】:
这很有趣。唯一的问题是这不允许自定义表达式的实际解析。由于数据类型的设置方式,不可能有一个 int 字段而是解析一个字符串(例如包含“>”)。这似乎是春天的限制。 @alexbt 嘿,您的提示对我非常有用。但在我的情况下,我需要为 gt、eq 和 lt 做一个年龄过滤器。我尝试使用它们各自的 singleBinding (gt, eq, lt) 为年龄属性提供不同的别名。但似乎一个属性不能有多个别名。你知道我如何将 gt、eq 和 lt 用于相同的属性吗?谢谢。以上是关于Spring - QueryDsl 支持的高级比较器的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot + Querydsl 框架,大大简化复杂查询操作!!
比较 Querydsl、jOOQ、JEQUEL、activejdbc、iciql 和其他查询 DSL