查询方法 public abstract java.util.List 的验证失败

Posted

技术标签:

【中文标题】查询方法 public abstract java.util.List 的验证失败【英文标题】:Validation failed for query for method public abstract java.util.List 【发布时间】:2018-09-23 20:05:27 【问题描述】:

我有一个基本的 SpringBoot 应用程序。使用 Spring Initializer、JPA、嵌入式 Tomcat、Thymeleaf 模板引擎,并将其打包为可执行的 JAR 文件。 SpringBoot 的版本是 2.0.1.RELEASE。 我用这个方法创建了一个从 CrudRepository 扩展的类存储库

@Query("select us.priceAlertsTapas.tapa from User us left join us.priceAlertsTapas  pat left join pat.tapa tapa where pat.priceAlert = ?1")
    List<Tapa> tapasByUserPriceAlert (PriceAlert pa);

但是当我启动项目时,我得到了这个错误:

Validation failed for query for method public abstract java.util.List



    at org.springframework.data.jpa.repository.query.SimpleJpaQuery.validateQuery(SimpleJpaQuery.java:93)
    at org.springframework.data.jpa.repository.query.SimpleJpaQuery.<init>(SimpleJpaQuery.java:63)
    at org.springframework.data.jpa.repository.query.JpaQueryFactory.fromMethodWithQueryString(JpaQueryFactory.java:76)
    at org.springframework.data.jpa.repository.query.JpaQueryFactory.fromQueryAnnotation(JpaQueryFactory.java:56)
    at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$DeclaredQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:139)
    at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:206)
    at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:79)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.lookupQuery(RepositoryFactorySupport.java:553)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.lambda$mapMethodsToQuery$1(RepositoryFactorySupport.java:546)
    at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
    at java.util.Iterator.forEachRemaining(Iterator.java:116)
    at java.util.Collections$UnmodifiableCollection$1.forEachRemaining(Collections.java:1049)
    at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
    at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.mapMethodsToQuery(RepositoryFactorySupport.java:548)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.lambda$new$0(RepositoryFactorySupport.java:538)
    at java.util.Optional.map(Optional.java:215)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.<init>(RepositoryFactorySupport.java:538)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:317)
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$3(RepositoryFactoryBeanSupport.java:287)
    at org.springframework.data.util.Lazy.getNullable(Lazy.java:141)
    at org.springframework.data.util.Lazy.get(Lazy.java:63)
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:290)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:102)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1761)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1698)
    ... 47 common frames omitted
Caused by: java.lang.NullPointerException: null
    at org.hibernate.hql.internal.ast.HqlSqlWalker.createFromJoinElement(HqlSqlWalker.java:424)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.joinElement(HqlSqlBaseWalker.java:3931)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElement(HqlSqlBaseWalker.java:3717)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElementList(HqlSqlBaseWalker.java:3595)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromClause(HqlSqlBaseWalker.java:720)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:576)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:313)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:261)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:266)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:189)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:141)
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:115)
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:77)
    at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:153)
    at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:553)
    at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:662)
    at org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:23)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:350)
    at com.sun.proxy.$Proxy105.createQuery(Unknown Source)
    at org.springframework.data.jpa.repository.query.SimpleJpaQuery.validateQuery(SimpleJpaQuery.java:87)
    ... 76 common frames omitted

使用提出的解决方案,我得到了同样的错误

这个查询我也有同样的错误 (?!?)

 @Query("select us.priceAlertsTapas.tapa from User us ")

这里是用户对象:

@Entity
@Table(name="t_user")
public class User implements Serializable, UserDetails 

...

@ManyToMany
    @JoinTable(
        name="t_user_price_alert_tapa",
        joinColumns=@JoinColumn(name="user_id", referencedColumnName="id"),
        inverseJoinColumns=@JoinColumn(name="price_alert_tapa_id", referencedColumnName="id"))
    private Set<PriceAlertTapa> priceAlertsTapas = new HashSet<>();

@Entity
@Table(name="t_price_alert")
public class PriceAlert implements Serializable 

    /**
     * 
     */
    private static final long serialVersionUID = 1L;


    public PriceAlert(int id) 
        super();
        this.id = id;
    


    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id; 

    private String name;

...

    

@Entity
@Table(name="t_price_alert_tapa")
public class PriceAlertTapa  implements Serializable 

    /**
     * 
     */
    private static final long serialVersionUID = 1L;


    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;


    public PriceAlertTapa(PriceAlert priceAlert, Tapa tapa) 
        super();
        this.tapa = tapa;
        this.priceAlert = priceAlert;
    

    private Tapa tapa;

    private PriceAlert priceAlert;
..

【问题讨论】:

您的查询返回us,它是一个用户,但如果您的列表类型为Tapa,您看到了吗? 你能发布你的实体类和 PriceAlert 类吗? 【参考方案1】:

我在@Query() 中使用表名时收到此错误,但您必须在@Query() 中使用类名:

不正确:

@Transactional
@Modifying
@Query("from SHIPPING_DOC e where e.fulfillmentId in ?1")
List<ShippingDocumentsJsonEntity> deleteByFulfillmentIdIn(List<String> fulfillmentIds);

正确:

@Transactional
@Modifying
@Query("from ShippingDocumentsJsonEntity e where e.fulfillmentId in ?1")
List<ShippingDocumentsJsonEntity> deleteByFulfillmentIdIn(List<String> fulfillmentIds);

【讨论】:

效果很好。谢谢。【参考方案2】:

由于 priceAlertsTapas 已设置,因此您不能使用点路径。

@Query("select us.priceAlertsTapas.tapa from User us")

首先你需要加入它

@Query("select pat.tapa from User us join us.priceAlertsTapas pat")

【讨论】:

@enPeris..ElgothdelaCiutat 如果您不指定顺序并且小吃是不同的,则可能在关系和结果中都设置了 @enPeris..ElgothdelaCiutat 如果我的回答对您有帮助,我可以接受赏金吗? 当然,抱歉 :-)【参考方案3】:

你有这个例外是因为你有错误的选择:

usUser

us.priceAlertsTapasSet

在那之后你真的想从中得到tapa,但Set 没有这样的字段。

【讨论】:

不,尝试使用pat.tapa 而不是us.priceAlertsTapas.tapa【参考方案4】:

如果您只对最右边的实体感兴趣,则没有理由使用左(外)连接 - 尽管我不确定这是否是您的查询验证失败的原因。

我会试试这个:

@Query("select tapa fom PriceAlertsTapas pat join pat.tapa tapa where pat.priceAlert = ?1")
List<Tapa> tapasByUserPriceAlert (PriceAlert pa);

如果给定的“tapa”可以与“价格提醒”有多个关联(例如,每个用户一个),那么您会在返回 List 中多次找到它。解决方案是将返回类型更改为 Set&lt;Tapa&gt; 或在查询中使用 "select distinct...."

另一方面,如果您的 PriceAlertsTapas 是简单的多对多关联,则使用 @ManyToMany JPA 注释可能会更好,最终使用 @JoinTable。例如,请参阅here。

【讨论】:

我在 User 实体中使用 @ManyToMany 关系和 PriceAlertsTapas

以上是关于查询方法 public abstract java.util.List 的验证失败的主要内容,如果未能解决你的问题,请参考以下文章

浅析java修饰符之public default protected private static final abstract

权限修饰符

接口的特点

Java单例模式详解

类与接口java中的接口与嵌套接口

C#中virtual 方法和abstract方法的区别