从 java 调用时如何将 Cursor 变量传递给 postgres 过程?
How to pass Cursor variable to postgres proceudre while calling from java?
我正在从 spring 引导应用程序调用一个 postgres 存储过程,它有 1 个文本类型的 IN 参数和 1 个 refcursor 类型的 INOUT 参数。如何从 CallableStatement 以外的 spring 引导应用程序调用此过程。
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$
谢谢
要使用 java.sql.CallableStatement
调用过程,请使用值为 call
或 callIfNoReturn
的连接参数 escapeSyntaxCallMode
,并且不指定 return 参数。正如 the documentation 所说:
escapeSyntaxCallMode = String
Specifies how the driver transforms JDBC escape call syntax into underlying SQL, for invoking procedures or functions. In escapeSyntaxCallMode=select
mode (the default), the driver always uses a SELECT statement (allowing function invocation only). In escapeSyntaxCallMode=callIfNoReturn
mode, the driver uses a CALL statement (allowing procedure invocation) if there is no return parameter specified, otherwise the driver uses a SELECT statement. In escapeSyntaxCallMode=call
mode, the driver always uses a CALL statement (allowing procedure invocation only).
问题是在 v11 中添加过程之前,JDBC 驱动程序将 CallableStatement
调用转换为函数调用,这对过程不起作用。
这是调用过程 p(IN integer, INOUT refcursor)
的代码示例,其中 refcursor
在 integer
的结果集上:
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();
}
}
我正在从 spring 引导应用程序调用一个 postgres 存储过程,它有 1 个文本类型的 IN 参数和 1 个 refcursor 类型的 INOUT 参数。如何从 CallableStatement 以外的 spring 引导应用程序调用此过程。
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$
谢谢
要使用 java.sql.CallableStatement
调用过程,请使用值为 call
或 callIfNoReturn
的连接参数 escapeSyntaxCallMode
,并且不指定 return 参数。正如 the documentation 所说:
escapeSyntaxCallMode = String
Specifies how the driver transforms JDBC escape call syntax into underlying SQL, for invoking procedures or functions. In
escapeSyntaxCallMode=select
mode (the default), the driver always uses a SELECT statement (allowing function invocation only). InescapeSyntaxCallMode=callIfNoReturn
mode, the driver uses a CALL statement (allowing procedure invocation) if there is no return parameter specified, otherwise the driver uses a SELECT statement. InescapeSyntaxCallMode=call
mode, the driver always uses a CALL statement (allowing procedure invocation only).
问题是在 v11 中添加过程之前,JDBC 驱动程序将 CallableStatement
调用转换为函数调用,这对过程不起作用。
这是调用过程 p(IN integer, INOUT refcursor)
的代码示例,其中 refcursor
在 integer
的结果集上:
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();
}
}