为什么Postgres查询无法识别@Query字符串中的字符串类型?

问题描述

我将Spring JPA存储库与Postgresql数据源一起使用。这是引起错误的有问题的查询

@Query("select ir from table ir " +
        "    join table1 dc on ir.ds.id = dc.id " +
        "join table2 p on dc.prj.id = p.id " +
        "join table3 pc on p.id = pc.prj.id " +
        "where (:int1 is null or p.id = :int1) " +
        "          and (:int2 is null or dc.id = :int2) " +
        "and (:str3 is null or concat(pc.id,'_',pc.cl) = :str3)")
List<EntityIR> findAllBy(@Param("int1") Integer int1,@Param("int2") Integer int2,@Param("str3") String str3);

当我将值3_it100传递到str3参数时,出现以下错误

Caused by: org.postgresql.util.PsqlException: ERROR: Could not determine data type of parameter $5
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2553) ~[postgresql-42.2.16.jar:42.2.16]
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2285) ~[postgresql-42.2.16.jar:42.2.16]
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:323) ~[postgresql-42.2.16.jar:42.2.16]
    at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:473) ~[postgresql-42.2.16.jar:42.2.16]
    at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:393) ~[postgresql-42.2.16.jar:42.2.16]
    at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:164) ~[postgresql-42.2.16.jar:42.2.16]
    at org.postgresql.jdbc.PgPreparedStatement.executeQuery(PgPreparedStatement.java:114) ~[postgresql-42.2.16.jar:42.2.16]
    at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeQuery(ProxyPreparedStatement.java:52) ~[HikariCP-3.4.5.jar:?]
    at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeQuery(HikariProxyPreparedStatement.java) ~[HikariCP-3.4.5.jar:?]
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:57) ~[hibernate-core-5.4.20.Final.jar:5.4.20.Final]
    at org.hibernate.loader.Loader.getResultSet(Loader.java:2341) ~[hibernate-core-5.4.20.Final.jar:5.4.20.Final]
    at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:2094) ~[hibernate-core-5.4.20.Final.jar:5.4.20.Final]
    at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:2056) ~[hibernate-core-5.4.20.Final.jar:5.4.20.Final]
    at org.hibernate.loader.Loader.doQuery(Loader.java:953) ~[hibernate-core-5.4.20.Final.jar:5.4.20.Final]
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:350) ~[hibernate-core-5.4.20.Final.jar:5.4.20.Final]
    at org.hibernate.loader.Loader.doList(Loader.java:2887) ~[hibernate-core-5.4.20.Final.jar:5.4.20.Final]
    at org.hibernate.loader.Loader.doList(Loader.java:2869) ~[hibernate-core-5.4.20.Final.jar:5.4.20.Final]
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2701) ~[hibernate-core-5.4.20.Final.jar:5.4.20.Final]
    at org.hibernate.loader.Loader.list(Loader.java:2696) ~[hibernate-core-5.4.20.Final.jar:5.4.20.Final]
    at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:506) ~[hibernate-core-5.4.20.Final.jar:5.4.20.Final]
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:400) ~[hibernate-core-5.4.20.Final.jar:5.4.20.Final]
    at org.hibernate.engine.query.spi.HQLQueryPlan.performlist(HQLQueryPlan.java:219) ~[hibernate-core-5.4.20.Final.jar:5.4.20.Final]
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1415) ~[hibernate-core-5.4.20.Final.jar:5.4.20.Final]
    at org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1565) ~[hibernate-core-5.4.20.Final.jar:5.4.20.Final]
    at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1533) ~[hibernate-core-5.4.20.Final.jar:5.4.20.Final]
    at org.hibernate.query.Query.getResultList(Query.java:165) ~[hibernate-core-5.4.20.Final.jar:5.4.20.Final]
    at org.springframework.data.jpa.repository.query.JpaQueryExecution$CollectionExecution.doExecute(JpaQueryExecution.java:126) ~[spring-data-jpa-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:88) ~[spring-data-jpa-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:154) ~[spring-data-jpa-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:142) ~[spring-data-jpa-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor$QueryMethodInvoker.invoke(QueryExecutorMethodInterceptor.java:195) ~[spring-data-commons-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:152) ~[spring-data-commons-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:130) ~[spring-data-commons-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80) ~[spring-data-commons-2.3.3.RELEASE.jar:2.3.3.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:367) ~[spring-tx-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118) ~[spring-tx-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) ~[spring-tx-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    ... 112 more

如何在查询中明确指定str3参数的类型?

解决方法

问题可能是您为str3提供了一个NULL值,并且NULL可以是任何数据类型,因此数据库无法猜测您的意思。

尝试明确:

"and (CAST (:str3 AS text) is null or concat(pc.id,'_',pc.cl) = CAST (:str3 AS text))"