4

我是 postgres 的新手,但我试图在 Postgres 11 中调用一个过程(新的“过程”而不是“函数”),从 java 作为 spring SimpleJDBCCall 调用(使用 Postgresql-42.2.5 jdbc 驱动程序)。但是,当我执行该过程时,我遇到了以下异常:

org.springframework.jdbc.BadSqlGrammarException: CallableStatementCallback; 糟糕的 SQL 语法 [{call pa_test_schema.pr_dosomething(?)}]; 嵌套异常是 org.postgresql.util.PSQLException:错误:pa_test_schema.pr_dosomething(bigint) 是一个过程 提示:要调用一个过程,请使用 CALL。位置:在 org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72) 在 org.springframework.jdbc.support 的 org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:101) 的第 15 位。 AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81) at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:

我的程序代码:

CREATE PROCEDURE pa_test_schema.pr_DoSomething
( P_input_ID IN inputs.input_ID%TYPE
) AS $$
BEGIN
    -- do something   
END; 
$$ LANGUAGE plpgsql;

我的java代码:

SimpleJdbcCallOperations pr_DoSomething =  new SimpleJdbcCall(jdbcTemplate)
        .withSchemaName("pa_test_schema")
        .withProcedureName("pr_DoSomething");
Map<String, Object> inputs = Maps.newHashMap();
inputs.put("p_input_id", 123456);

pr_DoSomething.execute(inputs);    

当我单步执行代码时,我可以看到驱动程序正在将可调用语句的 sql 修改为调用 postgres 函数所需的语法:

从 pa_test_schema.pr_dosomething(?) 中选择 * 作为结果

这是执行此转换的驱动程序中的方法: https ://github.com/pgjdbc/pgjdbc/blob/faab499853c56f67cb70fb242f75b918452f2a6f/pgjdbc/src/main/java/org/postgresql/core/Parser.java#L766

我了解过程仅在 Postgres 11 中引入(以前会使用返回 void 的函数),并且已阅读 postgres 驱动程序文档,但没有看到对调用过程而不是函数的任何引用。

这是否意味着当前的 postgres 驱动程序尚不支持此功能,还是我应该使用另一种方法?我应该只使用 postgres 函数吗?

4

1 回答 1

9

目前(从 Postgres 11.1 和驱动程序版本 42.2.5 开始)使用 a 的标准 JDBC 方法CallableStatement不能用于调用存储过程。

我并没有真正使用 Spring JDBC Template,但以下代码在普通 JDBC 中工作,并且应该适用于 Spring JDBC Tempalte:

Connection con = DriverManager.getConnection(...);
PreparedStatement pstmt = con.prepareStatement("call pa_test_schema.pr_DoSomething(?)");
pstmt.setInt(1, 42);
pstmt.execute();

请注意,这使用 Postgres 的call命令。不要将此与"{call ...}"a 的语法混淆CallableStatement


可以在此处此处的 JDBC 邮件列表中找到有关当前 CallableStatement 为何不起作用的更多详细信息

于 2018-12-05T14:04:22.463 回答