当 JDBC 遇上返回 Cursor

本文出处:https://www.modb.pro/db/400426

使用 jdbc 访问 PostgreSQL 或者 MogDB(openGauss)数据库里的 cursor 游标时,官方文档可查的资料较少,下面的示例供参考。

测试环境

JDBC:postgresql-42.3.5.jar

PG: 14.2

MogDB(openGauss): 3.0.0

测试背景

针对 function 和 procedure 返回 cursor 游标类型,通过 jdbc 如何调用。

测试 function:curtest1,通过 returns 返回游标类型

create or replace function curtest1()

returns refcursor

language plpgsql

as $function$

declare

cur refcursor;

begin

open cur for select id,data from fiverows;

return cur;

end;

$function$;

测试 procedure:curtest2,通过 out 参数返回游标类型

create or replace procedure curtest2(out cur refcursor)

language plpgsql

as $procedure$

begin

open cur for select id,data from fiverows;

end;

$procedure$;

测试 procedure:curtest3,通过 out 参数返回多个游标类型

create or replace procedure curtest3(out cur1 refcursor,out cur2 refcursor)

language plpgsql

as $procedure$

begin

open cur1 for select id,data from fiverows where id between 1 and 3;

open cur2 for select id,data from fiverows where id between 4 and 5;

end;

$procedure$;

表结构及数据

create table fiverows(id serial primary key,data text);

insert into fiverows(data) values('one'),('two'),

('three'),('four'),('five');

测试一:function 通过 returns 返回游标

function 返回游标在 PostgreSQL 或者 MogDB(openGauss)数据库里访问的代码参考如下:

public static void main(String[] args) throws Exception{
Class.forName("org.postgresql.Driver");
Connection conn = DriverManager.getConnection("jdbc:postgresql://***.***.***.***:1402/postgres","postgres","admin");
CallableStatement stmt = null;
ResultSet resultSet = null;
try{
conn.setAutoCommit(false);
stmt = conn.prepareCall("{? = call public.curtest1()}");;
stmt.registerOutParameter(1, Types.REF_CURSOR);
stmt.setCursorName("mycur1");
stmt.execute();
resultSet = (ResultSet) stmt.getObject(1);
while(resultSet.next()){
Integer id = (Integer)resultSet.getInt(1);
String data = (String) resultSet.getString(2);
System.out.println("id = "+id+", data = "+data);
} } catch (Exception e) {
e.printStackTrace();
}
conn.close();
}

注意下面这几点: 1.使用 CallableStatement 2.使用 Types.REF_CURSOR 注册输出参数 3.Statement 执行后,再通过 Statement 获取结果集

测试二:procedure 通过 out 参数返回游标

procedure 返回游标在 PostgreSQL 或者 MogDB(openGauss)数据库里有一点差异:主要是 escapeSyntaxCallMode 参数。

PostgreSQL

procedure 返回游标的 jdbc 代码跟上面 function 测试类似:

public static void main(String[] args) throws Exception{
Class.forName("org.postgresql.Driver");
Connection conn = DriverManager.getConnection("jdbc:postgresql://***.***.***.***:1402/postgres?escapeSyntaxCallMode=call", "postgres","admin");
CallableStatement stmt = null;
ResultSet resultSet = null;
try{
conn.setAutoCommit(false);
stmt = conn.prepareCall("{call public.curtest2(?)}");;
stmt.registerOutParameter(1, Types.REF_CURSOR); stmt.execute();
resultSet = (ResultSet) stmt.getObject(1);
while(resultSet.next()){
Integer id = (Integer)resultSet.getInt(1);
String data = (String) resultSet.getString(2);
System.out.println("id = "+id+", data = "+data);
}
} catch (Exception e) {
e.printStackTrace();
}
conn.close();
}

不过执行上面的代码客户端会报下面的错误:

错误信息提示并不是很明确,查找资料发现大概与 escapeSyntaxCallMode 参数有关,该参数的官方链接如下:https://jdbc.postgresql.org/documentation/head/connect.html

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).

自 PostgreSQL v11 开始支持 procedure,PostgreSQL JDBC 驱动也配套引入了 escapeSyntaxCallMode 参数,该参数有三种值,默认是第一种 func,系统理解为 function 来调用;第二种是 call,系统理解为 procedure 来调用;第三种是系统根据定义自动猜测。

上面的 connection 连接串加上 escapeSyntaxCallMode 参数,修改成:

jdbc:postgresql://...:1402/postgres?escapeSyntaxCallMode=call

则可正常执行

MogDB(openGauss)

procedure 返回游标的 jdbc 代码与 function 测试类似,并且也不需要设置 escapeSyntaxCallMode 参数。

procedure 创建语法有差异,代码如下:

create or replace procedure curtest2(out cur refcursor) as begin open cur for select id,data from fiverows; end;

测试三:procedure 通过 out 参数返回多个游标

返回多个游标与测试二类似,也是同样支持,在 PostgreSQL 也是需要设置 escapeSyntaxCallMode 参数,MogDB(openGauss)不需要设置。

PostgreSQL

jdbc 代码如下:

public static void main(String[] args) throws Exception{
Class.forName("org.postgresql.Driver");
Connection conn = DriverManager.getConnection("jdbc:postgresql://***.***.***.***:1402/postgres?escapeSyntaxCallMode=call","postgres","admin");
CallableStatement stmt = null;
ResultSet resultSet = null;
try{
conn.setAutoCommit(false);
stmt = conn.prepareCall("{call public.curtest3(?,?)}");;
stmt.registerOutParameter(1, Types.REF_CURSOR);
stmt.registerOutParameter(2, Types.REF_CURSOR);
stmt.execute();
resultSet = (ResultSet) stmt.getObject(1);
System.out.println("cursor1 data:");
while(resultSet.next()){
Integer id = (Integer)resultSet.getInt(1);
String data = (String) resultSet.getString(2);
System.out.println("id = "+id+", data = "+data);
}
resultSet = (ResultSet) stmt.getObject(2);
System.out.println("cursor2 data:");
while(resultSet.next()){
Integer id = (Integer)resultSet.getInt(1);
String data = (String) resultSet.getString(2);
System.out.println("id = "+id+", data = "+data);
} } catch (Exception e) {
e.printStackTrace();
}
conn.close();
}

测试结果如下:

MogDB(openGauss)

与测试二类似,不需要设置 escapeSyntaxCallMode 参数。

procedure 创建语法有差异,代码如下:

create or replace procedure curtest3(out cur1 refcursor,out cur2 refcursor)

as

begin

open cur1 for select id,data from fiverows where id between 1 and 3;

open cur2 for select id,data from fiverows where id between 4 and 5;

end;

结论通过 jdbc 访问 function 里的 returns cursor 或者 procedure 里的 out cursor 类型都支持。 区别在于 procedure 的 out cursor 类型,在 PostgreSQL 需要设置 escapeSyntaxCallMode=call,MogDB(openGauss)数据库不需要。

当JDBC遇上返回Cursor的更多相关文章

  1. 谁还没遇上过NoClassDefFoundError咋地——浅谈字节码生成与热部署

    谁还没遇上过NoClassDefFoundError咋地--浅谈字节码生成与热部署 前言 在Java程序员的世界里,NoClassDefFoundError是一类相当令人厌恶的错误,因为这类错误通常非 ...

  2. dynamic遇上ADO.NET

    传说中的dynamic dynamic是个不合群.不按规则办事的家伙,可以说是个异形,但更恐怖的是它又是无所不知的,任何事情都难不了它(咳咳,它似乎与Lambda表达式是死对头).这令人想起<死 ...

  3. 前端遇上Go: 静态资源增量更新的新实践

    前端遇上Go: 静态资源增量更新的新实践https://mp.weixin.qq.com/s/hCqQW1F8FngPPGZAisAWUg 前端遇上Go: 静态资源增量更新的新实践 原创: 洋河 美团 ...

  4. 当微信小程序遇上filter~

    在微信小程序的开发过程中,当你想要实现不同页面间的数据绑定,却为此抓耳饶腮时,不妨让微信小程序与filter 来一场完美的邂逅,相信会给你带来别样的惊喜~ 前段时间被安利了一个很实用的公众号-前端早读 ...

  5. 当 Go struct 遇上 Mutex

    struct 是我们写 Go 必然会用到的关键字, 不过当 struct 遇上一些比较特殊类型的时候, 你注意过你的程序是否正常吗 ? 一段代码 type URL struct { Ip string ...

  6. 当 SQL Server(mssql-jdbc) 遇上 BigDecimal → 精度丢失,真坑!

    开心一刻 中午和哥们一起喝茶 哥们说道:晚上喝酒去啊 我:不去,我女朋友过生日 哥们瞪大眼睛看着我:你有病吧,充气的过什么生日 我生气到:有特么生产日期的好吧 需求背景 系统对接了外部系统,调用外部系 ...

  7. MVC遇上bootstrap后的ajax表单模型验证

    MVC遇上bootstrap后的ajax表单验证 使用bootstrap后他由他自带的样式has-error,想要使用它就会比较麻烦,往常使用jqueyr.validate的话只有使用他自己的样式了, ...

  8. 敏捷遇上UML-需求分析及软件设计最佳实践(郑州站 2014-6-7)

      邀请函: 尊敬的阁下:我们将在郑州为您奉献高端知识大餐,当敏捷遇上UML,会发生怎样的化学作用呢?首席专家张老师将会为您分享需求分析及软件设计方面的最佳实践,帮助您掌握敏捷.UML及两者相结合的实 ...

  9. 敏捷遇上UML—软创基地马年大会(广州站 2014-4-19)

        我们将在广州为您奉献高端知识大餐,当敏捷遇上UML,会发生怎样的化学作用呢?首席专家张老师将会为您分享需求分析及软件设计方面的最佳实践,帮助您掌握敏捷.UML及两者相结合的实战技巧. 时间:2 ...

  10. 敏捷遇上UML——软创基地马年大会(深圳站 2014-3-15)

    邀请函: 尊敬的阁下: 我们将在深圳为您奉献高端知识大餐,当敏捷遇上UML,会发生怎样的化学作用呢?首席专家张老师将会为您分享需求分析及软件设计方面的最佳实践,帮助您掌握敏捷.UML及两者相结合的实战 ...

随机推荐

  1. 【Azure 事件中心】使用Apache Flink 连接 Event Hubs 出错 Kafka error: No resolvable bootstrap urls

    问题描述 参考Github上 Event Hub的示例代码(Using Apache Flink with Event Hubs for Apache Kafka Ecosystems : https ...

  2. 学习ASP.NET Core Blazor编程系列文章之目录

    学习ASP.NET Core Blazor编程系列一--综述 学习ASP.NET Core Blazor编程系列二--第一个Blazor应用程序(上) 学习ASP.NET Core Blazor编程系 ...

  3. JavaScript获取href的值

    1.当href的值为正常网址时: <!DOCTYPE html> <html> <head> <title></title> <met ...

  4. Spring配置xml自定义事务管理器

    上一篇博客讲解了Spring配置xml事务,使用的是Spring框架提供的事务管理器. 在本篇博文当中,来讲解一下使用自定义的事务管理方式. 把上一篇博文当中的这个配置 <bean id=&qu ...

  5. pollute 污染 pol=por=pro 向前 lut=释放 结合ps软件里面lut概念记忆

    pollute 污染 pol = por = pro = 向前 lut = 释放 (ps里面有lut的概念) e 动词 向前释放 -> 污染 弄脏 简单记忆 poll / ute poll - ...

  6. python tkinter - pickle 持久化

    查看当前python版本命令 cmd - python 现在当前版本是 3.8.8 tkinter - tool kits interface

  7. Navicat 通过 Http通道 连接远程 Mysql

    https://jingyan.baidu.com/article/3d69c551aa54dff0cf02d7a0.html 注意本机ip填写 localhost

  8. 【LLM】在Colab上使用免费T4 GPU进行Chinese-Llama-2-7b-4bit推理

    一.配置环境 1.打开colab,创建一个空白notebook,在[修改运行时环境]中选择15GB显存的T4 GPU. 2.pip安装依赖python包 !pip install --upgrade ...

  9. 基于ads1299的可穿戴脑电信号采集之性能调试总结

    一 前言 问题背景: 最近做项目,遇到了一个问题,就是采集的信号有噪声,在这里做了很多尝试.   二 测试步骤 A 内部方波信号质量,通过测试发现内部方波信号质量特别好.这个说明了软件和存储这块,没啥 ...

  10. stable diffusion安装及使用

    最近在看这个,踩了一些坑,现在有点头绪了,记录如下 安装很简单,直接git下载下来,然后进到根目录执行./web-ui.py,第一次启动你没有模型他会帮你下载个默认模型,我有模型了,就先把这个模型放到 ...