Postgresql 11:存储过程调用错误 - 要调用过程,请使用 CALL、Java

Posted

技术标签:

【中文标题】Postgresql 11:存储过程调用错误 - 要调用过程,请使用 CALL、Java【英文标题】:Postgresql 11: Stored Procedure call error - To call a procedure, use CALL, Java 【发布时间】:2021-04-18 04:03:38 【问题描述】:

为了交易目的,我将 PGsql 函数转换为过程 (v11)。但是在从 Java 代码调用该过程时,Java 代码会抛出以下异常:

2021-01-10 21:52:56,604 WARN  [ForkJoinPool.commonPool-worker-1] o.h.e.j.spi.SqlExceptionHelper(144) - SQL Error: 0, SQLState: 42809
2021-01-10 21:52:56,605 ERROR [ForkJoinPool.commonPool-worker-1] o.h.e.j.spi.SqlExceptionHelper(146) - ERROR: some_procedure_name(character varying, character varying) is a procedure
  Hint: To call a procedure, use CALL.
  Position: 15

我正在使用 Spring Data JPA 的 @Procedure(name = "some_procedure_name"),并且此过程在实体类中声明为 @NamedStoredProcedure。问题是,这个注解仍然像 PG 版本 11 之前一样将其作为函数方式调用。

任何帮助。

【问题讨论】:

【参考方案1】:

在 PostgreSQL 11 之后,PostgreSQL JDBC 驱动团队在 PostgreSQL 驱动版本 42.2.16 中引入了一个 ENUM 名称​​EscapeSyntaxCallMode。我们可以在创建数据库连接或DataSource 对象时使用此枚举。这个枚举有 3 种类型的值:

    "func" - 当我们总是想调用函数时设置它。 "call" - 当我们总是想调用过程时设置它。 "callIfNoReturn" - 它检查调用函数/过程中的返回类型,如果返回类型存在,PostgreSQL 将其视为函数并将其作为函数方式调用。否则将其称为过程方式。所以在我的项目中,我使用了这个“callIfNoReturn”,因为我希望 PostgreSQL 自动检测我是在调用函数还是过程。

因此,要解决此问题,您只需按照以下步骤操作:

    将您的 PostgreSQL JDBC 驱动程序版本从任何旧版本升级到 pom.xml 或 gradle 中的 42.2.16 或更高版本。

    <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
        <version>42.2.16</version>
    </dependency>
    

    当然,您的机器上必须安装 PostgreSQL 服务器版本 >= 11 才能创建过程。

    如果您使用的是 Spring,那么在创建数据源对象时,您需要在 "jdbcUrl" 中附加 escapeSyntaxCallMode 作为查询字符串,如下所示:

    <bean id="dataSource" parent="com.zaxxer.hikari.HikariDataSource">
        <property name="jdbcUrl" value="jdbc:postgresql://localhost:5432/dev_db?escapeSyntaxCallMode=$cibase.db.app.procedureCallPolicy"/>
        <property name="username" value="$cibase.db.app.user"/>
        <property name="password" value="$cibase.db.app.password"/>
    </bean>
    

    ?escapeSyntaxCallMode=$cibase.db.app.procedureCallPolicy:这里我从属性文件中选择枚举值,但是你可以根据你的要求直接输入"func"/"call"/"callIfNoReturn"中的任何枚举值。

现在你运行你的代码,它会正常工作。

注意: 无论您是使用纯 JDBC 代码还是 Spring Data Jpa 中的 @Procedure,您都无需更改过程调用方式。

更多详情请点击此链接https://github.com/pgjdbc/pgjdbc

【讨论】:

如果答案解决了您的问题,请接受。请不要将其保留为“未答复”。接受答案有助于以后可能遇到相同问题的提问者。

以上是关于Postgresql 11:存储过程调用错误 - 要调用过程,请使用 CALL、Java的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 JDBC 调用 PostgreSQL 存储过程

JPA 和 PostgreSQL:如何调用具有 void 返回类型的存储过程?

调用PostgreSQL存储过程,找不到函数名的问题

使用 Dapper (C#) 调用 PostgreSQL 存储过程

Mybatis调用PostgreSQL存储过程实现数组入参传递

DataGrip PostgreSQL 存储过程错误