【问题标题】:Can I call a postgres "Procedure" (not "function") from java using the postgres JDBC driver?我可以使用 postgres JDBC 驱动程序从 java 调用 postgres“过程”(而不是“函数”)吗?
【发布时间】:2019-05-07 02:28:55
【问题描述】:

我是 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);    

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

【问题讨论】:

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


    【解决方案1】:

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

    我并没有真正使用 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 命令。不要将此与 CallableStatement"{call ...}" 语法混淆。


    有关当前 CallableStatement 为何不起作用的更多详细信息,请参阅 JDBC 邮件列表 herehere

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-09
      • 1970-01-01
      • 1970-01-01
      • 2021-02-02
      • 2019-08-17
      • 2013-04-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多