QueryDsl 对地图字段键的 Web 查询概述试一些细节其他发现问题更换豆子从 http 参数创建地图搜索谓词
概述
鉴于
- Spring Data JPA, Spring Data Rest, QueryDsl
- 一个实体
Meetup
- 带字段
Map<String,String> properties
- 作为
MEETUP_PROPERTY
@ElementCollection
- 作为
- 带字段
- 一个
MeetupRepository
- 延伸
QueryDslPredicateExecutor<Meetup>
- 延伸
我期待
的 Web 查询
GET /api/meetup?properties[aKey]=aValue
以仅返回具有指定键和值的属性条目的 Meetups:aKey=aValue。
但是,这对我不起作用。我错过了什么?
试
简单字段
简单的字段工作,如名称和描述:
GET /api/meetup?name=whatever
集合字段的工作方式,如参与者:
GET /api/meetup?participants.name=whatever
但不是此地图字段。
自定义 QueryDsl 绑定
我已尝试通过拥有存储库来自定义绑定
extend QuerydslBinderCustomizer<QMeetup>
并覆盖
customize(QuerydslBindings bindings, QMeetup meetup)
方法,但在命中方法时,lambda 中的绑定代码不是。customize()
编辑:了解到这是因为评估查询参数的方法不允许它与它内部保存的映射匹配 - 其中有您的自定义绑定。QuerydslBindings
pathSpecs
一些细节
Meetup.properties field
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name = "MEETUP_PROPERTY", joinColumns = @JoinColumn(name = "MEETUP_ID"))
@MapKeyColumn(name = "KEY")
@Column(name = "VALUE", length = 2048)
private Map<String, String> properties = new HashMap<>();
自定义查询sl绑定
编辑:见上文;事实证明,这对我的代码没有任何作用。
public interface MeetupRepository extends PagingAndSortingRepository<Meetup, Long>,
QueryDslPredicateExecutor<Meetup>,
QuerydslBinderCustomizer<QMeetup> {
@Override
default void customize(QuerydslBindings bindings, QMeetup meetup) {
bindings.bind(meetup.properties).first((path, value) -> {
BooleanBuilder builder = new BooleanBuilder();
for (String key : value.keySet()) {
builder.and(path.containsKey(key).and(path.get(key).eq(value.get(key))));
}
return builder;
});
}
其他发现
-
QuerydslPredicateBuilder.getPredicate()
要求尝试 2 种方法从 返回路径,以便它可以创建可以使用的谓词。QuerydslBindings.getPropertyPath()
QuerydslAwareRootResourceInformationHandlerMethodArgumentResolver.postProcess()
- 1 是查看自定义绑定。我看不到任何表达地图查询的方法
- 2 是默认为 Spring 的 bean 路径。同样的表达问题。如何表达地图?因此,自动创建谓词看起来是不可能的。很好 - 我可以手动完成,如果我可以钩入
QuerydslPredicateBuilder.getPredicate()
QuerydslAwareRootResourceInformationHandlerMethodArgumentResolver.postProcess()
如何重写该类或替换 Bean?它被实例化并在 bean 声明中作为 Bean 返回。RepositoryRestMvcConfiguration.repoRequestArgumentResolver()
- 我可以通过声明我自己的bean来覆盖该bean,但它没有被使用。
repoRequestArgumentResolver
- 它被 s 覆盖。我无法通过设置它或来强制它。
RepositoryRestMvcConfiguration
@Primary
@Ordered(HIGHEST_PRECEDENCE)
- 我可以通过显式组件扫描来强制它,但这也搞砸了Spring Boot的自动配置,因为它会导致在任何自动配置运行之前处理bean声明。除其他事项外,这会导致杰克逊以不需要的方式序列化响应。
RepositoryRestMvcConfiguration.class
RepositoryRestMvcConfiguration's
- 它被 s 覆盖。我无法通过设置它或来强制它。
问题
好吧 - 看起来我期望的支持并不存在。
所以问题就变成了:我如何正确地覆盖豆子?repoRequestArgumentResolver
BTW - 是尴尬的非公开的。:/QuerydslAwareRootResourceInformationHandlerMethodArgumentResolver