【问题标题】:How to pass Cursor variable to postgres proceudre while calling from java?从java调用时如何将Cursor变量传递给postgres过程?
【发布时间】:2021-11-08 15:11:29
【问题描述】:

我正在从 Spring Boot 应用程序调用一个 postgres 存储过程,该应用程序具有 1 个文本类型的 IN 参数和 1 个 refcursor 类型的 INOUT 参数。如何从 CallableStatement 以外的 springboot 应用程序调用此过程。

public class CallProc {
    public static void main(String[] args) throws ClassNotFoundException, java.sql.SQLException {
        
        Class.forName("org.postgresql.Driver");
        
        String url = "jdbc:postgresql://azure.com/test";
        Properties props = new Properties();
        props.setProperty("user","test");
        props.setProperty("password","test");
        props.setProperty("ssl","true");
        props.setProperty("escapeSyntaxCallMode", "callIfNoReturn");
        Connection conn = DriverManager.getConnection(url, props);

        // need a transaction
        conn.setAutoCommit(false);

        java.sql.CallableStatement callableStatement =
            conn.prepareCall("{call myProc(?, ?)}");

        callableStatement.setString(1, "user");
        callableStatement.setObject(2, null);

        callableStatement.registerOutParameter(2, java.sql.Types.REF_CURSOR);

        callableStatement.execute();
       
        java.sql.ResultSet rs =
            (java.sql.ResultSet) callableStatement.getObject(2);

        while (rs.next())
            System.out.println(rs.getInt(1));

        rs.close();
        conn.commit();

        conn.close();
    }
}

而我的程序定义是这样的,

CREATE OR REPLACE PROCEDURE myapp.MyProc(
     in_user_id TEXT,
     INOUT user_roles refcursor)
language plpgsql
AS $BODY$
DECLARE

DERIVED USER_ID VARCHAR(50);

BEGIN
//body
...
//
END
$BODY$

谢谢

【问题讨论】:

  • 为什么要以其他方式调用过程?
  • 因为 CallableStatement 给出了 org.postgresql.util.PSQLException:错误:helloworld() 是一个过程 提示:要调用一个过程,请使用 CALL。这个错误@LaurenzAlbe 可以在这里检查 PG JDBC 驱动程序限制的限制highgo.ca/2020/11/25/…

标签: java postgresql stored-procedures


【解决方案1】:

要使用java.sql.CallableStatement 调用过程,请使用带有值callcallIfNoReturn 的连接参数escapeSyntaxCallMode,并且不指定返回参数。正如the documentation 所说:

escapeSyntaxCallMode = 字符串

指定驱动程序如何将 JDBC 转义调用语法转换为底层 SQL,以调用过程或函数。在escapeSyntaxCallMode=select 模式(默认)下,驱动程序始终使用 SELECT 语句(仅允许函数调用)。在escapeSyntaxCallMode=callIfNoReturn 模式下,如果没有指定返回参数,则驱动程序使用 CALL 语句(允许过程调用),否则驱动程序使用 SELECT 语句。在escapeSyntaxCallMode=call 模式下,驱动程序始终使用 CALL 语句(仅允许过程调用)。

问题是在 v11 中添加过程之前,JDBC 驱动程序将 CallableStatement 调用转换为函数调用,这对过程不起作用。

这是一个调用过程p(IN integer, INOUT refcursor) 的代码示例,其中refcursor 位于integers 的结果集上:

public class CallProc {
    public static void main(String[] args) throws ClassNotFoundException, java.sql.SQLException {
        Class.forName("org.postgresql.Driver");

        java.sql.Connection conn =
            java.sql.DriverManager.getConnection(
                "jdbc:postgresql:test?user=laurenz&password=something&escapeSyntaxCallMode=callIfNoReturn"
            );

        // need a transaction
        conn.setAutoCommit(false);

        java.sql.CallableStatement callableStatement =
            conn.prepareCall("{call p(?::text, ?::refcursor)}");

        callableStatement.setInt(1, 5);
        callableStatement.setObject(2, null);

        callableStatement.registerOutParameter(2, java.sql.Types.REF_CURSOR);

        callableStatement.execute();
       
        java.sql.ResultSet rs =
            (java.sql.ResultSet) callableStatement.getObject(2);

        while (rs.next())
            System.out.println(rs.getInt(1));

        rs.close();
        conn.commit();

        conn.close();
    }
}

【讨论】:

  • 我想喜欢这个 { ? = 调用 myProc(?,?)}
  • 我正在尝试这样 // myProc(IN text,INOUT refcursor) query = "call myProc(?,?)"; CallabelStatement stmt = prepareCall(query); stmt.setString(1,"userID"); stmt.registerOutParameter(2,Types.REF_CUR);在这里我收到错误,因为语句没有声明 OUT 参数 use { ? = call(?,?)query = "call myProc(?,?)"; stmt.setString(1,"userID"); stmt.registerOutParameter(2,Types.REF_CUR); ERROR-> 语句未声明 OUT 参数使用 { ? = 调用(?,?)
  • 当我尝试使用这个字符串查询 = "{ ? = call myProc(?,?)}"; CallabelStatement stmt = prepareCall(query); stmt.registerOutParameter(1,Types.REF_CUR); stmt.setString(2,"userID); stmt.registerOutParameter(3,Types.REF_CUR); 错误 -> 函数 myProc 不存在。
  • 我已经修改了答案并添加了一个例子。
  • 嗨 Laurenz,即使我指定了 escapeSyntaxCallMode=call 或 escapeSyntaxCallMode=callIfNoReturn,它给出的错误是函数 myProc(character varying, unknown) 不存在。没有函数匹配给定的名称和参数。添加显式类型转换
猜你喜欢
  • 1970-01-01
  • 2023-04-11
  • 2017-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多