【发布时间】:2018-02-09 21:00:21
【问题描述】:
概述
给定
- Spring Data JPA、Spring Data Rest、QueryDsl
-
Meetup实体- 带有
Map<String,String> properties字段- 以
@ElementCollection的形式坚持在MEETUP_PROPERTY表中
- 以
- 带有
-
MeetupRepository- 扩展
QueryDslPredicateExecutor<Meetup>
- 扩展
我希望
网络查询
GET /api/meetup?properties[aKey]=aValue
只返回具有指定键和值的属性条目的聚会:aKey=aValue。
但是,这对我不起作用。 我错过了什么?
试过
简单字段
使用简单的字段,例如名称和描述:
GET /api/meetup?name=whatever
收集字段像参与者一样工作:
GET /api/meetup?participants.name=whatever
但不是这个 Map 字段。
自定义 QueryDsl 绑定
我尝试通过拥有存储库来自定义绑定
extend QuerydslBinderCustomizer<QMeetup>
并覆盖
customize(QuerydslBindings bindings, QMeetup meetup)
方法,但是当customize() 方法被命中时,lambda 内部的绑定代码没有。
编辑:了解到这是因为 QuerydslBindings 评估查询参数的方式不会让它与它内部持有的 pathSpecs 映射匹配 - 其中包含您的自定义绑定。
一些细节
Meetup.properties 字段
@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<>();
自定义 querydsl 绑定
编辑:见上文;事实证明,这对我的代码没有任何作用。
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()要求QuerydslBindings.getPropertyPath()尝试 2 种方法来返回路径,以便它可以创建一个QuerydslAwareRootResourceInformationHandlerMethodArgumentResolver.postProcess()可以使用的谓词。- 1 是查看自定义绑定。我没有看到任何表达地图查询的方法
- 2 默认为 Spring 的 bean 路径。那里有同样的表达问题。你如何表达一张地图?
所以看起来不可能让
QuerydslPredicateBuilder.getPredicate()自动创建谓词。 很好 - 我可以手动完成,如果我可以连接到QuerydslAwareRootResourceInformationHandlerMethodArgumentResolver.postProcess()
如何覆盖该类或替换 bean?它在 RepositoryRestMvcConfiguration.repoRequestArgumentResolver() bean 声明中被实例化并作为 bean 返回。
- 我可以通过声明我自己的
repoRequestArgumentResolverbean 来覆盖该 bean,但它没有被使用。- 它被
RepositoryRestMvcConfigurations 覆盖。我无法通过设置@Primary或@Ordered(HIGHEST_PRECEDENCE)来强制它。 - 我可以通过显式组件扫描
RepositoryRestMvcConfiguration.class来强制它,但这也会扰乱 Spring Boot 的自动配置,因为它会导致RepositoryRestMvcConfiguration's要处理的 bean 声明 在任何自动配置运行之前。除其他外,这会导致 Jackson 以不需要的方式序列化响应。
- 它被
问题
嗯 - 看起来我期望的支持不存在。
所以问题变成了:
如何正确覆盖repoRequestArgumentResolver bean?
顺便说一句 - QuerydslAwareRootResourceInformationHandlerMethodArgumentResolver 尴尬地不公开。 :/
【问题讨论】:
标签: java spring spring-data-jpa spring-data-rest querydsl