如何在 JPQL 中正确执行 LIKE 和 CASE 子句

How to properly execute LIKE and CASE clause in JPQL

我想执行一个在 sql 中有效的查询,但是当我尝试使用 @Query 注释 运行 它时,程序就死了,我正在尝试将一个字符串与一个substring,我不知道该怎么做。我已经尝试了很长时间来弄清楚如何解决这些问题。

package stpt.Repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import stpt.entities.StopTimes;

import java.util.Date;
import java.util.List;

public interface StopTimesRepository extends JpaRepository<StopTimes,String> {
  @Query("SELECT arrivalTime FROM StopTimes st WHERE tripId IN (:id)")
  List<String> findBySpecificTime(@Param("id") String id);
  @Query("SELECT distinct st.arrivalTime \n" +
          "FROM StopTimes st, Trips t, Routes r, Stops s \n" +
          "WHERE r.routeShortName IN (:short_name)\n" +
          "AND t.tripHeadsign IN (:heading)\n" +
          "AND st.tripId=t.tripId\n" +
          "AND t.routeId=r.routeId \n" +
          "AND s.stopId=st.stopId\n" +
          "AND CASE WHEN dayname(current_date())='saturday' OR dayname(current_date())='sunday' THEN t.serviceId like '%-sd' else t.serviceId like '%-lv' END\n" +
          "AND CASE HOUR(current_time())=11 THEN st.arrivalTime LIKE '23%' else st.arrivalTime LIKE '23%' END\n" +
          "AND s.stopName IN (:stop)")
  List<String> findByArrivalTime(@Param("short_name") String short_name, @Param("heading") String heading, @Param("stop") String stop);
}
st<String> findByArrivalTime(@Param("short_name") String short_name, @Param("heading") String heading, @Param("stop") String stop);
}

以及来自控制台的主要错误:

2021-06-26 01:51:45.744 ERROR 12100 --- [  restartedMain] o.h.hql.internal.ast.ErrorTracker        : line 8:103: unexpected token: like
2021-06-26 01:51:45.751 ERROR 12100 --- [  restartedMain] o.h.hql.internal.ast.ErrorTracker        : line 8:103: unexpected token: like

antlr.NoViableAltException: unexpected token: like

at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.4.3.jar:2.4.3]

2021-06-26 01:51:45.753 ERROR 12100 --- [  restartedMain] o.h.hql.internal.ast.ErrorTracker        : line 8:115: unexpected token: else
2021-06-26 01:51:45.754 ERROR 12100 --- [  restartedMain] o.h.hql.internal.ast.ErrorTracker        : line 8:115: unexpected token: else

antlr.NoViableAltException: unexpected token: else

at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.4.3.jar:2.4.3]

2021-06-26 01:51:45.756  WARN 12100 --- [  restartedMain] o.hibernate.hql.internal.ast.HqlParser   : HHH000203: processEqualityExpression() : No expression to process!
2021-06-26 01:51:45.757 ERROR 12100 --- [  restartedMain] o.h.hql.internal.ast.ErrorTracker        : line 8:120: unexpected token: t
2021-06-26 01:51:45.760 ERROR 12100 --- [  restartedMain] o.h.hql.internal.ast.ErrorTracker        : line 8:120: unexpected token: t

antlr.NoViableAltException: unexpected token: t

at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.4.3.jar:2.4.3]

2021-06-26 01:51:45.763 ERROR 12100 --- [  restartedMain] o.h.hql.internal.ast.ErrorTracker        : line 9:28: expecting EOF, found ')'
2021-06-26 01:51:45.765 ERROR 12100 --- [  restartedMain] o.h.hql.internal.ast.ErrorTracker        : line 9:28: expecting EOF, found ')'

antlr.MismatchedTokenException: expecting EOF, found ')'
   at antlr.Parser.match(Parser.java:211) ~[antlr-2.7.7.jar:na]

at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.4.3.jar:2.4.3]

2021-06-26 01:51:45.785  WARN 12100 --- [  restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'appController': Unsatisfied dependency expressed through field 'services'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'services': Unsatisfied dependency expressed through field 'stopTimesRepository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'stopTimesRepository' defined in stpt.Repository.StopTimesRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.List stpt.Repository.StopTimesRepository.findByArrivalTime(java.lang.String,java.lang.String,java.lang.String)!

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2021-06-26 01:51:45.892 ERROR 12100 --- [  restartedMain] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'appController': Unsatisfied dependency expressed through field 'services'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'services': Unsatisfied dependency expressed through field 'stopTimesRepository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'stopTimesRepository' defined in stpt.Repository.StopTimesRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.List stpt.Repository.StopTimesRepository.findByArrivalTime(java.lang.String,java.lang.String,java.lang.String)!

Caused by: java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: like near line 8, column 103 [SELECT distinct st.arrivalTime 
FROM stpt.entities.StopTimes st, stpt.entities.Trips t, stpt.entities.Routes r, stpt.entities.Stops s 
WHERE r.routeShortName IN (:short_name)
AND t.tripHeadsign IN (:heading)
AND st.tripId=t.tripId
AND t.routeId=r.routeId 
AND s.stopId=st.stopId
AND CASE WHEN dayname(current_date())='saturday' OR dayname(current_date())='sunday' THEN t.serviceId like '%-sd' else t.serviceId like '%-lv' END
AND CASE HOUR(current_time())=11 THEN st.arrivalTime LIKE '23%' else st.arrivalTime LIKE '23%' END
AND s.stopName IN (:stop)]

Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: like near line 8, column 103 [SELECT distinct st.arrivalTime 
FROM stpt.entities.StopTimes st, stpt.entities.Trips t, stpt.entities.Routes r, stpt.entities.Stops s 
WHERE r.routeShortName IN (:short_name)
AND t.tripHeadsign IN (:heading)
AND st.tripId=t.tripId
AND t.routeId=r.routeId 
AND s.stopId=st.stopId
AND CASE WHEN dayname(current_date())='saturday' OR dayname(current_date())='sunday' THEN t.serviceId like '%-sd' else t.serviceId like '%-lv' END
AND CASE HOUR(current_time())=11 THEN st.arrivalTime LIKE '23%' else st.arrivalTime LIKE '23%' END
AND s.stopName IN (:stop)]

我通过将 nativequery 切换为 true 来解决它,允许使用简单的 sql。

@Query(value = "SELECT distinct arrival_time, stop_name\n" +
            "FROM stop_times st, trips t, routes r, stops s \n" +
            "WHERE r.route_short_name=:short_name\n" +
            "AND t.trip_headsign=:heading\n" +
            "AND st.trip_id=t.trip_id\n" +
            "AND t.route_id=r.route_id \n" +
            "AND s.stop_id=st.stop_id\n" +
            "AND IF(DAYOFWEEK(CURDATE())=7 OR DAYOFWEEK(CURDATE())=1, t.service_id LIKE '%-sd', t.service_id LIKE '%-lv')\n" +
            "AND IF(HOUR(CURTIME())=23, st.arrival_time LIKE '23:%',23)\n" +
            "AND s.stop_name=:stop",nativeQuery = true)
    List<String> findByArrivalTime(@Param("short_name") String short_name, @Param("heading") String heading, @Param("stop") String stop);