Postgresql 使用“case-when”时出现Spring Hibernate查询语法异常
该查询在PostgreSQL中用作本机查询。但在通过Hibernate将其传递给Spring数据JPA@Query时失败。哪种语法是编写查询的正确语法Postgresql 使用“case-when”时出现Spring Hibernate查询语法异常,postgresql,hibernate,jpa,spring-data-jpa,hql,Postgresql,Hibernate,Jpa,Spring Data Jpa,Hql,该查询在PostgreSQL中用作本机查询。但在通过Hibernate将其传递给Spring数据JPA@Query时失败。哪种语法是编写查询的正确语法 @Repository public interface ProcessoJudicialRepository extends JpaRepository<ProcessoJudicial, Long> { @Query("select p from ProcessoJudicial p where" + " cas
@Repository
public interface ProcessoJudicialRepository extends JpaRepository<ProcessoJudicial, Long> {
@Query("select p from ProcessoJudicial p where"
+ " case when :numero is not null then (p.numero = :numero) else true end"
+ " and case when :advogadoId is not null then (p.advogado_id = :advogadoId) else true end"
+ " and case when :assuntoId is not null then (p.assuntoId = :assuntoId) else true end"
+ " and case when :modalidadeId is not null then (p.modalidade_id = :modalidadeId) else true end")
Page<ProcessoJudicial> find(@Param("numero") String numero, @Param("advogadoId") Long advogadoId,
@Param("assuntoId") Long assuntoId, @Param("modalidadeId") Long modalidadeId,
Pageable pageable);
}
启动此例外:
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected AST node: case near line 1, column 77 [select p from com.rcsoyer.servicosjuridicos.domain.ProcessoJudicial p where case when :numero is not null then (p.numero = :numero) else true end and case when :advogadoId is not null then (p.advogado_id = :advogadoId) else true end and case when :assuntoId is not null then (p.assuntoId = :assuntoId) else true end and case when :modalidadeId is not null then (p.modalidade_id = :modalidadeId) else true end]
at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:74)
at org.hibernate.hql.internal.ast.ErrorCounter.throwQueryException(ErrorCounter.java:91)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:272)
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)
... 125 common frames omitted
我试着解决另一个问题
尽管这在我的案例中不起作用。该JPQL的第77列是开头的case关键字。如JPA规范中所示,需要一个简单的条件表达式,而case表达式不是JPA规范中的表达式
simple_cond_expression ::=
comparison_expression |
between_expression |
in_expression |
like_expression |
null_comparison_expression |
empty_collection_comparison_expression |
collection_member_expression |
exists_expression
所以你可以有一个WHERE子句
(case_expression) = some_value
但不是
(case_expression)
靠自己
请注意,并非所有JPA提供程序都有Hibernate所具有的这种限制,并且确实可以很好地对其进行评估,但这是JPA规范的一个扩展,例如DataNucleus JPA。我没有找到一种简洁的方法来编写带有CASE-WHEN的查询,因此我改为使用and和OR。与我以前的效果完全相同,但现在在两个方面都有效,直接用于Postgres和Hibernate 最后的代码是:
@Query("from #{#entityName} p where"
+ " ((:numero is not null and p.numero = :numero) or (:numero is null))"
+ " and ((:advogadoId is not null and p.advogado.id = :advogadoId) or (:advogadoId is null))"
+ " and ((:assuntoId is not null and p.assunto.id = :assuntoId) or (:assuntoId is null))"
+ " and ((:modalidadeId is not null and p.modalidade.id = :modalidadeId) or (:modalidadeId is null))")
Page<ProcessoJudicial> query(@Param("numero") String numero, @Param("advogadoId") Long advogadoId,
@Param("assuntoId") Long assuntoId, @Param("modalidadeId") Long modalidadeId, Pageable pageable);
尽管如此,如果有人知道正确的查询编写方法,可能更简单、更清晰,使用CASE-WHEN,甚至是上面查询的改进,我很乐意知道 实际上,当:advogadoId时,不能将参数用作case。你需要考虑我为什么不能使用它的任何可能的重复,@Nidhi257?@Nidhi257实际上JPA规范说你可以在CASE表达式中有一个参数。这是一种肮脏的方式,但你的答案对我的项目有帮助!谢谢分享