简体   繁体   中英

JPQL subquery with exists

I am currently working on a SpringBoot app that allows users to book a table in a specific restaurant. The user can filter the restaurants according to various preferences. One of these are the food types they serve.

The restaurant class has a list of foods as an attribute as seen below.

package entities;

import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.NonNull;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Data
@NoArgsConstructor
@Entity(name = "Restaurant")
public class Restaurant extends User{
@Column(name = "name", unique=true, nullable = false)
@NonNull
private String name;

@Column(name = "rut", nullable = false)
@NonNull
private String RUT;

@Column(name = "address")
private String address;

@Column(name = "phone")
private Long phoneNumber;

@Column(name = "max_capacity", nullable = false)
@NonNull
private Integer maxCapacity;

@ManyToOne
@JoinColumn(name = "neighbourhood", nullable = false)
@NonNull
private Neighbourhood neighbourhood;

@ManyToMany(fetch=FetchType.EAGER)
private List<Food> foods = new ArrayList<>();

    public Restaurant(String email, String username, String password, String 
    name, String RUT, Integer maxCapacity, Neighbourhood neighbourhood) {
    super(email, username, password);
    this.name = name;
    this.RUT = RUT;
    this.maxCapacity = maxCapacity;
    this.neighbourhood = neighbourhood;
    }
}

Then, the query I wrote after searching everywhere how to do it is the following:

package labtic.database;

import entities.Food;
import entities.Neighbourhood;
import entities.Restaurant;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface RestaurantRepository extends             
JpaRepository<Restaurant,String> {

@Query("SELECT r2 FROM Restaurant r2 WHERE EXISTS (SELECT r, COUNT(r) FROM 
   Restaurant r INNER JOIN r.foods rf WHERE rf IN :foods AND r2=r GROUP BY r 
   HAVING COUNT(r)=:size) AND r.name LIKE '%:name%' AND r.neighbourhood IN 
   :neighbourhoods AND r.maxCapacity >= :maxCapacity")

List<Restaurant> findByFilters(@Param("name") String name, @Param("foods")     
List<Food> foods, @Param("neighbourhoods") List<Neighbourhood> 
neighbourhoods, @Param("maxCapacity")Integer maxCapacity);
}

The last part of the Stacktrace (the one I think is relevant) is the following:

Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: Invalid 
path: 'r.name' [SELECT r2 FROM entities.Restaurant r2 WHERE EXISTS (SELECT 
r, COUNT(r) FROM entities.Restaurant r INNER JOIN r.foods rf WHERE rf IN 
:foods AND r2=r GROUP BY r HAVING COUNT(r)=:size) AND r.name LIKE '%:name%' 
AND r.neighbourhood IN :neighbourhoods AND r.maxCapacity >= :maxCapacity]
at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:74) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.hql.internal.ast.ErrorCounter.throwQueryException(ErrorCounter.java:91) ~ [hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:272) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:189) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:141) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:115) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:77) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:153) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:553) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:662) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
... 78 common frames omitted

If I need to add more information about my code to this question please let me know. It is my first question in Stackoverflow so sorry if I am not making myself clear.

Thanks in advance!

You need to use r2 instead of r outside the subquery

@Query("SELECT r2 FROM Restaurant r2 
   WHERE EXISTS 
  (SELECT r, COUNT(r) FROM 
   Restaurant r INNER JOIN r.foods rf WHERE rf IN :foods AND r2=r GROUP BY r 
   HAVING COUNT(r)=:size) 
   AND r2.name LIKE '%:name%' AND r2.neighbourhood IN 
   :neighbourhoods AND r.maxCapacity >= :maxCapacity")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM