J'ai une application SpringBoot de base. Utilisation de Spring Initializer, JPA, de Tomcat, du moteur de modèle Thymeleaf intégré et du package en tant que fichier JAR exécutable . La version de SpringBoot est la version 2.0.1.RELEASE. J'ai créé un référentiel de classes qui s'étend de CrudRepository avec cette méthode
@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);
Mais quand j'ai initié le projet, j'ai eu cette erreur:
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
Avec la solution proposée j'ai eu la même erreur
Avec cette requête j'ai aussi la même erreur (?!?)
@Query("select us.priceAlertsTapas.tapa from User us ")
Voici l'objet utilisateur:
@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<>();
}
et
@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;
...
}
et
@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;
..
}
Puisque priceAlertsTapas est défini, vous ne pouvez pas utiliser le chemin de points.
@Query("select us.priceAlertsTapas.tapa from User us")
D'abord vous devez le rejoindre
@Query("select pat.tapa from User us join us.priceAlertsTapas pat")
Vous n'avez aucune raison d'utiliser une jointure gauche (extérieure) si vous n'êtes intéressé que par l'entité la plus à droite - bien que je ne sois pas sûr que ce soit la raison pour laquelle la validation de votre requête échoue.
Je voudrais essayer ceci:
@Query("select tapa fom PriceAlertsTapas pat join pat.tapa tapa where pat.priceAlert = ?1")
List<Tapa> tapasByUserPriceAlert (PriceAlert pa);
Si un "tapa" donné peut avoir plusieurs associations à une "alerte de prix" (par exemple, une par utilisateur), vous le retrouverez plusieurs fois dans votre déclaration List
. La solution consiste à changer le type de retour en Set<Tapa>
ou à utiliser "select distinct...."
dans votre requête.
Si, en revanche, votre PriceAlertsTapas est une simple association plusieurs à plusieurs, il peut être préférable d'utiliser l'annotation JPA @ManyToMany, éventuellement avec @JoinTable. Voir, par exemple, ici .
Vous avez cette exception parce que vous avez mal sélectionné:
us
est User
us.priceAlertsTapas
est Set
après cela, vous devez obtenir tapa
mais Set
ne possède pas ce champ.