我可以使用postgres JDBC驱动程序从Java调用postgres“过程”(不是“函数”)吗?

时间:2018-12-05 13:39:34

标签: stored-procedures jdbc spring-jdbc postgresql-11

我是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。位置:15,   org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:101)     在   org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)     在   org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)     在   org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)     在   org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1402)     在   org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:1065)     在   org.springframework.jdbc.core.JdbcTemplate.call(JdbcTemplate.java:1104)     在   org.springframework.jdbc.core.simple.AbstractJdbcCall.executeCallInternal(AbstractJdbcCall.java:414)     在   org.springframework.jdbc.core.simple.AbstractJdbcCall.doExecute(AbstractJdbcCall.java:397)     在   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);    

单步执行代码时,我可以看到驱动程序正在将callable语句的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函数吗?

1 个答案:

答案 0 :(得分:3)

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

我实际上并没有使用Spring JDBC模板,但是以下代码可在纯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 ...}"的{​​{1}}语法混淆。


在JDBC邮件列表herehere中可以找到关于为什么当前CallableStatement不起作用的更多详细信息