使用"时的"时的Spring Hibernate Query语法异常

时间:2018-03-09 03:59:10

标签: postgresql hibernate jpa spring-data-jpa hql

该查询在PostgreSQL中用作本机查询。但是在使用Hibernate传递它以在Spring Data JPA @Query中使用时失败了。哪个是编写查询的正确语法?

@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

我尝试了另一个问题的解决方案

Question appointed as solution for mine

虽然这在我的案例中没有用。

2 个答案:

答案 0 :(得分:0)

该JPQL的第77列是开头&#34;案例&#34;关键词。 JPQL BNF(如JPA规范中所示)期望一个简单的条件表达式,&#34; case表达式&#34;不是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)。

答案 1 :(得分:0)

我没有找到一种干净简单的方法来编写查询&#34; CASE WHEN&#34;所以我改为使用&#34; AND&#34;和&#34;或&#34;。具有与之前完全相同的效果,但现在可以两种方式工作,直接在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);

虽然,如果有人知道编写查询的正确方法,可能会以更简单,更清洁的方式,使用&#34; CASE WHEN&#34;,甚至上述查询的改进,我会很高兴知道。