我可以使用 postgres JDBC 驱动程序从 java 调用 postgres "Procedure"(不是 "function")吗?

Can I call a postgres "Procedure" (not "function") from java using the postgres JDBC driver?

我是 postgres 的新手,但我正在尝试调用 Postgres 11 中的过程(新的 "procedure" 而不是 "function"),从 java 作为 spring SimpleJDBCCall(使用 Postgresql-42.2.5 jdbc 驱动程序)。但是,当我执行该过程时遇到以下异常:

org.springframework.jdbc.BadSqlGrammarException: CallableStatementCallback; bad SQL grammar [{call pa_test_schema.pr_dosomething(?)}]; nested exception is org.postgresql.util.PSQLException: ERROR: pa_test_schema.pr_dosomething(bigint) is a procedure Hint: To call a procedure, use CALL. Position: 15 at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:101) at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72) at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81) at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81) at org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1402) at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:1065) at org.springframework.jdbc.core.JdbcTemplate.call(JdbcTemplate.java:1104) at org.springframework.jdbc.core.simple.AbstractJdbcCall.executeCallInternal(AbstractJdbcCall.java:414) at org.springframework.jdbc.core.simple.AbstractJdbcCall.doExecute(AbstractJdbcCall.java:397) at org.springframework.jdbc.core.simple.SimpleJdbcCall.execute(SimpleJdbcCall.java:193)

我的程序代码:

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 函数所需的语法:

select * from pa_test_schema.pr_dosomething(?) as result

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

我知道过程只在 Postgres 11 中引入(以前会使用返回 void 的函数)并且已经通读了 postgres 驱动程序文档,但没有看到任何关于调用过程而不是函数的参考。

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

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

我并没有真正使用 Spring JDBC 模板,但是下面的代码可以正常工作 JDBC 并且应该适用于 Spring JDBC模板:

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

请注意,这使用了 Postgres 的 call 命令。不要将此与 CallableStatement.

"{call ...}" 语法混淆

可以在 JDBC 邮件列表 here and here

中找到有关当前 CallableStatement 为何不起作用的更多详细信息