Spring @QuerydslPredicate问题 [英] Spring @QuerydslPredicate Questions

查看:413
本文介绍了Spring @QuerydslPredicate问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Spring Boot 1.3.2.RELEASE

Spring Boot 1.3.2.RELEASE

QueryDSL 3.7.2

QueryDSL 3.7.2

QueryDSL Maven插件1.1.3

QueryDSL Maven Plugin 1.1.3

Hibernate 4.3.11.Final

Hibernate 4.3.11.Final

目前,我有一个Spring Boot应用程序,它使用Spring Data JPA(由Hibernate支持)具有一些基本的CRUD功能,并使用Spring Data Envers进行审计。我还有以下端点来检索实体列表:

Currently, I have a Spring Boot application that has some basic CRUD functionality using Spring Data JPA (backed by Hibernate), and auditing using Spring Data Envers. I also have the following endpoint to retrieve a list of entities from:


http:// localhost:8080 / test-app / list

现在,我想使用 @QuerydslPredicate 注释,rel =noreferrer> Spring提供的新QueryDSL支持。这适用于大多数字段或子实体,但它似乎不适用于子实体的集合。文档,博客文章等似乎不包括这种情况 - 我能找到的唯一信息是它支持简单集合的in(即字符串集合等)。

Now, I wanted to use the new QueryDSL support that Spring offers through the @QuerydslPredicate annotation. This works fine for most fields or sub-entities, but it doesn't appear to work for collections of sub-entities. The documentation, blog posts, etc. don't seem to cover this case - and the only information I could find is that it supports "in" for simple collections (i.e. collections of String, etc.).

所以,我的实体设置如下:

So, my entity is set up something like so:

Person.java

@Data
@Entity
@Audited
public class Person {

    @Id
    private long id;

    private String name;

    private List<Pet> pets = new ArrayList<>();

}

Pet.java

@Data
@Entity
@Audited
public class Pet {

    @Id
    private long id;

    private int age;

}

我使用 com.mysema.maven:apt-maven-plugin ,它使用以下字段生成我的 QPerson

I generate my Q classes using the com.mysema.maven:apt-maven-plugin, which generates my QPerson with the following field:

public final ListPath<com.test.Pet, com.test.QPet> pets = this.<com.test.Pet, com.test.QPet>createList("pets", com.test.Pet.class, com.test.QPet.class, PathInits.DIRECT2);

如果我尝试查询这个,我会得到一个例外:

If I try to query on this though, I get an exception:

查询:


http:// localhost:8080 / test-app / list?pets.age = 5

例外:

10:21:37,523 ERROR [org.springframework.boot.context.web.ErrorPageFilter] (http-/127.0.0.1:8080-1) Forwarding to error page from request [/list] due to exception [null]: java.lang.NullPointerException
    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:]
    at org.springframework.data.querydsl.binding.QuerydslPredicateBuilder.reifyPath(QuerydslPredicateBuilder.java:188) [spring-data-commons-1.11.2.RELEASE.jar:]
    at org.springframework.data.querydsl.binding.QuerydslPredicateBuilder.getPath(QuerydslPredicateBuilder.java:167) [spring-data-commons-1.11.2.RELEASE.jar:]
    at org.springframework.data.querydsl.binding.QuerydslPredicateBuilder.invokeBinding(QuerydslPredicateBuilder.java:136) [spring-data-commons-1.11.2.RELEASE.jar:]
    at org.springframework.data.querydsl.binding.QuerydslPredicateBuilder.getPredicate(QuerydslPredicateBuilder.java:111) [spring-data-commons-1.11.2.RELEASE.jar:]
    at org.springframework.data.web.querydsl.QuerydslPredicateArgumentResolver.resolveArgument(QuerydslPredicateArgumentResolver.java:106) [spring-data-commons-1.11.2.RELEASE.jar:]
    at org.springframework.data.web.querydsl.QuerydslPredicateArgumentResolver.resolveArgument(QuerydslPredicateArgumentResolver.java:48) [spring-data-commons-1.11.2.RELEASE.jar:]
    at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:78) [spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]

现在这个查询看起来好像正在尝试解析propertyPath Person.pets.age 。它正确地将 Person.pets 标识为 ListPath ,然后尝试识别 CompanyAddress.addressLine1 (这似乎是正确的)。问题是,它试图使用实体路径来获取类,即 ListPath 而不是 QPet

Now this query look like it's trying to resolve the propertyPath Person.pets.age. It correctly identifies Person.pets as a ListPath, and then tries to identify CompanyAddress.addressLine1 (which seems correct). The problem is, it tries to use the entity path to get the class, which is the ListPath instead of the QPet:

Field field = ReflectionUtils.findField(entityPath.getClass(), path.getSegment());
Object value = ReflectionUtils.getField(field, entityPath);

以下查询按预期工作:


http:// localhost:8080 / test-app / list ?name = Bob

我的期望是使用?pets.age = 5 ,将构建以下谓词:

My expectation was that by using ?pets.age=5, the following predicate would be built:

QPerson.person.pets.any().age.eq(5)

目前Spring的QuerydslPredicate支持是否可行?或者我应该从查询参数手动构建谓词吗?

Is this currently possible with Spring's QuerydslPredicate support? Or should I manually build the predicates from the query parameters?

另外一个问题是,以下可能与QuerydslPredicate有关。假设我在pet上有firstName和lastName,我想运行只有 name = Bob 的查询:

As an additional question, is the following possible with QuerydslPredicate. Say I have a firstName and lastName on pet, and I want to run a query with just name=Bob:


http:// localhost:8080 / test-app / pet / list?name = Bob

我希望查询谓词的构建如下:

I would want the query predicate to be built like this:

final BooleanBuilder petBuilder = new BooleanBuilder();
petBuilder.and(QPet.firstName.equals("Bob").or(QPet.lastName.equals("Bob")));

这可能吗?通过查看 QuerydslBinderCustomizer 的自定义方法,它似乎不会,因为您需要绑定Q类的字段。我猜我不想支持。

Is that possible? From looking at the customize method of the QuerydslBinderCustomizer it doesn't seem like it would be, since you need to bind off a field of the Q class. I'm guessing that what I want to do is not supported.

如果这些都不可能,那么我将坚持手动创建谓词,然后传递在存储库中。

If these aren't possible, then I'll stick with manually creating the predicate, and passing that on to the repository.

推荐答案

我遇到了同样的错误。但是我注意到使用QuerydslAnnotationProcessor插件(而不是JPA注释处理器)允许我按预期查询实体的子集合。您只需使用@QueryEntity注释标记所有实体类。 (JPA注释处理器自动为@Entity注释类生成查询类。)

I ran into the same error. However I noticed that using the QuerydslAnnotationProcessor plugin (instead of the JPA annotation processor) allows me to query sub collections of entities as expected. You just have to mark all of your entity classes with the @QueryEntity annotation. (The JPA annotation processor automatically generates query classes for @Entity annotated classes.)

在你的pom中:

          <plugin>
                <groupId>com.mysema.maven</groupId>
                <artifactId>apt-maven-plugin</artifactId>
                <version>1.1.3</version>
                <executions>
                    <execution>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>process</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>target/generated-sources/annotations</outputDirectory>
                            <processor>com.querydsl.apt.QuerydslAnnotationProcessor</processor>
                        </configuration>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>com.querydsl</groupId>
                        <artifactId>querydsl-apt</artifactId>
                        <version>4.1.3</version>
                    </dependency>
                </dependencies>
            </plugin>

我相信我遇到了您遇到的异常,因为我从JPA Annotation Processor更改为QuerydslAnnotationProcessor由于某种原因我不记得了,并且忽略了使用@QueryEntity注释来标记相关列表的实体类。但是我也相信我有另一个Spring-Data-Rest\JPA支持的API,它使用2017年8月构建的JPA Annotation Processor,我相信查询子集合的实体按预期工作。我将能够在今天晚些时候确认,并提供相关依赖项的版本(如果是这种情况)。也许这个问题已得到解决。

I'm believe I was running into the exception you encountered because I changed from the JPA Annotation Processor to the QuerydslAnnotationProcessor, for some reason I do not recall, and neglected to mark the entity class of the list in question with the @QueryEntity annotation. However I also believe I have another Spring-Data-Rest\JPA backed API that uses the JPA Annotation Processor built in August 2017, and I believe querying sub collections of entities works as expected. I'll be able to confirm that later today, and provide the versions of the relevant dependencies if that is the case. Perhaps this issue has been fixed.

这篇关于Spring @QuerydslPredicate问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆