Spring Data REST 的 QueryDSL 集成,用于查询实体中集合映射的子属性
Posted
技术标签:
【中文标题】Spring Data REST 的 QueryDSL 集成,用于查询实体中集合映射的子属性【英文标题】:Spring Data REST's QueryDSL integration for querying subproperties of collection mapping in an entity 【发布时间】:2016-05-12 21:26:00 【问题描述】:进行了一些深入的研究,发现带有 query-dsl 的 spring-data-rest 可以让 REST API 客户端轻松过滤实体的大多数属性。
这个问题也很有用: Can Spring Data REST's QueryDSL integration be used to perform more complex queries?
正如 Dennis Laumen 已经提到的,QueryDslPredicateExecutor
和 QuerydslBinderCustomizer
提供了一些引人注目的功能,但缺乏文档。
我要破解的具体功能是:
我有一个 @ManyToMany 映射到 UserGroup 实体的用户实体
public class User
@Id
@GeneratedValue
private Long id;
@Column(name = "user_name")
private String username;
@ManyToMany
@JoinTable(name = "fs_user_group_map", joinColumns = @JoinColumn(name = "user_id") , inverseJoinColumns = @JoinColumn(name = "group_id") )
private List<UserGroup> userGroups;
我正在尝试获取所有用户,其中一个用户组的名称应与文本匹配:
所以我要访问的 URI 是:/users?userGroups.name=Admin
但这会出错。
19:08:04.423|ERROR|o.s.d.r.w.RepositoryRestExceptionHandler|null
java.lang.NullPointerException: null
at org.springframework.util.ReflectionUtils.getField(ReflectionUtils.java:143) ~[spring-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.data.querydsl.binding.QuerydslPredicateBuilder.reifyPath(QuerydslPredicateBuilder.java:185) ~[spring-data-commons-1.11.2.RELEASE.jar:na]
at org.springframework.data.querydsl.binding.QuerydslPredicateBuilder.reifyPath(QuerydslPredicateBuilder.java:188) ~[spring-data-commons-1.11.2.RELEASE.jar:na]
at org.springframework.data.querydsl.binding.QuerydslPredicateBuilder.getPath(QuerydslPredicateBuilder.java:167) ~[spring-data-commons-1.11.2.RELEASE.jar:na]
at org.springframework.data.querydsl.binding.QuerydslPredicateBuilder.invokeBinding(QuerydslPredicateBuilder.java:136) ~[spring-data-commons-1.11.2.RELEASE.jar:na]
at org.springframework.data.querydsl.binding.QuerydslPredicateBuilder.getPredicate(QuerydslPredicateBuilder.java:111) ~[spring-data-commons-1.11.2.RELEASE.jar:na]
at org.springframework.data.rest.webmvc.config.QuerydslAwareRootResourceInformationHandlerMethodArgumentResolver.postProcess(QuerydslAwareRootResourceInformationHandlerMethodArgumentResolver.java:91) ~[spring-data-rest-webmvc-2.4.2.RELEASE.jar:na]
at org.springframework.data.rest.webmvc.config.RootResourceInformationHandlerMethodArgumentResolver.resolveArgument(RootResourceInformationHandlerMethodArgumentResolver.java:92) ~[spring-data-rest-webmvc-2.4.2.RELEASE.jar:na]
at org.springframework.data.rest.webmvc.config.RootResourceInformationHandlerMethodArgumentResolver.resolveArgument(RootResourceInformationHandlerMethodArgumentResolver.java:40) ~[spring-data-rest-webmvc-2.4.2.RELEASE.jar:na]
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:78) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:162) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:129) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:814) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:737) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:969) [spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:860) [spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:687) [javax.servlet-api-3.1.0.jar:3.1.0]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:845) [spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) [javax.servlet-api-3.1.0.jar:3.1.0]
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:812) [jetty-servlet-9.2.14.v20151106.jar:9.2.14.v20151106]
围绕 QuerydslPredicateBuilder.reifyPath 进行的一些调试使我了解到 userGroups 是一个 ListPath
并且尝试使用反射来查找其上的属性“名称”。但我实际需要的 query-dsl 路径是 user.userGroups.any().name
在 URL 上尝试任何其他语法,但在 QuerydslPredicateBuilder.getPredicate
中似乎不会被识别为有效的 PropertyPath
。
这是一个错误吗?
【问题讨论】:
这方面有什么更新吗? 不,我希望 spring-data 团队的人能澄清一下 我想我们可能需要在这里做出贡献:github.com/spring-projects/spring-data-jpa 看来这是一个错误 - jira.spring.io/browse/DATAREST-694 我认为该错误并不能真正解决我提到的问题,但该错误的解决方案可以提供帮助。我投了赞成票:) 【参考方案1】:就我而言,升级到 spring-data Ingalls-SR7 解决了这个问题。
【讨论】:
以上是关于Spring Data REST 的 QueryDSL 集成,用于查询实体中集合映射的子属性的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Spring-Data-Rest 中实现细粒度的访问控制?
初入spring boot(八 )Spring Data REST