JPA:如何在 SELECT 查询中使用 CASE
JPA: How to use CASE in SELECT Query
在下面的查询中,我想 select 基于最小和最大年龄的程序,但关键是每个程序都没有必要有最小和最大年龄,所以我想签入查询是否存在最小或最大年龄比检查参数 'age' 它应该位于最小和最大年龄
之间
查询
@Query("Select p from Program p where (CASE WHEN p.minimumAge!=null AND p.maximumAge==null THEN p.minimumAge<=:age ELSE 0),(CASE WHEN p.minimumAge!=null AND p.maximumAge!=null THEN p.minimumAge<=:age AND p.maximumAge>=:age ELSE 0)")
List<Program> programs(@Param("age")int age);
错误
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: = near line 1, column 108 [Select p from com.ivl.MySportsAcademy.model.Program p where (CASE WHEN p.minimumAge!=null AND p.maximumAge==null THEN p.minimumAge<=:age ELSE 0),(CASE WHEN p.minimumAge!=null AND p.maximumAge!=null THEN p.minimumAge<=:age AND p.maximumAge>=:age ELSE 0)]
at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:74) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.hql.internal.ast.ErrorCounter.throwQueryException(ErrorCounter.java:91) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:288) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:187) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:142) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:115) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:76) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:150) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.internal.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:302) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:240) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:1894) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:291) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
... 48 common frames omitted
几个问题:
- 错误指向第 108 列,即
p.maximumAge==null
- SQL 中没有 ==
,只有 =
- 您将无法像 if 语句那样使用 CASE WHEN THEN 来动态 add/remove where 子句。
但是,您应该能够使用 COALESCE
来替代 null,因此如果您这样做:
Select p
from Program p
where COALESCE(p.maximumAge, :age) >= :age
and COALESCE(p.minimumAge, :age) <= :age
然后每当程序的最大年龄为 NULL 时,比较结果为 :age <= :age
(始终为真)。最小值相同。
希望对您有所帮助
在下面的查询中,我想 select 基于最小和最大年龄的程序,但关键是每个程序都没有必要有最小和最大年龄,所以我想签入查询是否存在最小或最大年龄比检查参数 'age' 它应该位于最小和最大年龄
之间查询
@Query("Select p from Program p where (CASE WHEN p.minimumAge!=null AND p.maximumAge==null THEN p.minimumAge<=:age ELSE 0),(CASE WHEN p.minimumAge!=null AND p.maximumAge!=null THEN p.minimumAge<=:age AND p.maximumAge>=:age ELSE 0)")
List<Program> programs(@Param("age")int age);
错误
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: = near line 1, column 108 [Select p from com.ivl.MySportsAcademy.model.Program p where (CASE WHEN p.minimumAge!=null AND p.maximumAge==null THEN p.minimumAge<=:age ELSE 0),(CASE WHEN p.minimumAge!=null AND p.maximumAge!=null THEN p.minimumAge<=:age AND p.maximumAge>=:age ELSE 0)]
at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:74) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.hql.internal.ast.ErrorCounter.throwQueryException(ErrorCounter.java:91) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:288) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:187) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:142) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:115) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:76) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:150) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.internal.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:302) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:240) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:1894) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:291) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
... 48 common frames omitted
几个问题:
- 错误指向第 108 列,即
p.maximumAge==null
- SQL 中没有==
,只有=
- 您将无法像 if 语句那样使用 CASE WHEN THEN 来动态 add/remove where 子句。
但是,您应该能够使用 COALESCE
来替代 null,因此如果您这样做:
Select p
from Program p
where COALESCE(p.maximumAge, :age) >= :age
and COALESCE(p.minimumAge, :age) <= :age
然后每当程序的最大年龄为 NULL 时,比较结果为 :age <= :age
(始终为真)。最小值相同。
希望对您有所帮助