当JDBC遇上返回Cursor
当 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的更多相关文章
- 谁还没遇上过NoClassDefFoundError咋地——浅谈字节码生成与热部署
谁还没遇上过NoClassDefFoundError咋地--浅谈字节码生成与热部署 前言 在Java程序员的世界里,NoClassDefFoundError是一类相当令人厌恶的错误,因为这类错误通常非 ...
- dynamic遇上ADO.NET
传说中的dynamic dynamic是个不合群.不按规则办事的家伙,可以说是个异形,但更恐怖的是它又是无所不知的,任何事情都难不了它(咳咳,它似乎与Lambda表达式是死对头).这令人想起<死 ...
- 前端遇上Go: 静态资源增量更新的新实践
前端遇上Go: 静态资源增量更新的新实践https://mp.weixin.qq.com/s/hCqQW1F8FngPPGZAisAWUg 前端遇上Go: 静态资源增量更新的新实践 原创: 洋河 美团 ...
- 当微信小程序遇上filter~
在微信小程序的开发过程中,当你想要实现不同页面间的数据绑定,却为此抓耳饶腮时,不妨让微信小程序与filter 来一场完美的邂逅,相信会给你带来别样的惊喜~ 前段时间被安利了一个很实用的公众号-前端早读 ...
- 当 Go struct 遇上 Mutex
struct 是我们写 Go 必然会用到的关键字, 不过当 struct 遇上一些比较特殊类型的时候, 你注意过你的程序是否正常吗 ? 一段代码 type URL struct { Ip string ...
- 当 SQL Server(mssql-jdbc) 遇上 BigDecimal → 精度丢失,真坑!
开心一刻 中午和哥们一起喝茶 哥们说道:晚上喝酒去啊 我:不去,我女朋友过生日 哥们瞪大眼睛看着我:你有病吧,充气的过什么生日 我生气到:有特么生产日期的好吧 需求背景 系统对接了外部系统,调用外部系 ...
- MVC遇上bootstrap后的ajax表单模型验证
MVC遇上bootstrap后的ajax表单验证 使用bootstrap后他由他自带的样式has-error,想要使用它就会比较麻烦,往常使用jqueyr.validate的话只有使用他自己的样式了, ...
- 敏捷遇上UML-需求分析及软件设计最佳实践(郑州站 2014-6-7)
邀请函: 尊敬的阁下:我们将在郑州为您奉献高端知识大餐,当敏捷遇上UML,会发生怎样的化学作用呢?首席专家张老师将会为您分享需求分析及软件设计方面的最佳实践,帮助您掌握敏捷.UML及两者相结合的实 ...
- 敏捷遇上UML—软创基地马年大会(广州站 2014-4-19)
我们将在广州为您奉献高端知识大餐,当敏捷遇上UML,会发生怎样的化学作用呢?首席专家张老师将会为您分享需求分析及软件设计方面的最佳实践,帮助您掌握敏捷.UML及两者相结合的实战技巧. 时间:2 ...
- 敏捷遇上UML——软创基地马年大会(深圳站 2014-3-15)
邀请函: 尊敬的阁下: 我们将在深圳为您奉献高端知识大餐,当敏捷遇上UML,会发生怎样的化学作用呢?首席专家张老师将会为您分享需求分析及软件设计方面的最佳实践,帮助您掌握敏捷.UML及两者相结合的实战 ...
随机推荐
- C# 多线程(17):小总结
前言 本篇内容是小总结和过渡,看完这篇后,就要开始继续学习 C# 多线程中的知识点啦~. 前面,经过 16 篇的学习,我们学习了多线程.锁.线程池.任务.同步.异步等知识,还没有使用到 async.a ...
- linux服务器文件实时同步
linux服务器文件实时同步 1 背景说明 在做系统集群部署时,涉及到两个或多个服务器之间文件同步.在软件层面linux服务环境找到以下两种同步方式 利用linux NFS功能将网络共享文件挂载成本地 ...
- BIGO 的数据管理与应用实践
本文首发于 Nebula Graph Community 公众号 本文整理自 BIGO 在 nMeetp 上的主题分享,主要介绍 BIGO 过去一年在数据管理建设方面的理解和探索.而 BIGO 数据管 ...
- [Python] 超简单的 超星学习通自动签到
目录 概述 代码 其他的 文件编码问题 windows 和 linux下换行符不同的问题 概述 今天两节课的签到都错过了 /(ㄒoㄒ)/~~ 所以决定花点时间做一个自动签到的工具 经过观察发现超星的结 ...
- C++ 模板的笔记1
C++模板的笔记1 C++ 函数模板 函数模板的定义 函数模板是一种可以生成不同类型函数的函数声明.函数模板的参数类型不是固定的,而是在调用时由实参类型推导出来. 语法: template <t ...
- RocketMQ(7) 消费幂等
1 什么是消费幂等 当出现消费者对某条消息重复消费的情况时,重复消费的结果与消费一次的结果是相同的,并且多次消 费并未对业务系统产生任何负面影响,那么这个消费过程就是消费幂等的. 幂等:若某操作执行多 ...
- ip 表单验证 vue iview
ip 表单验证 vue iview template <Row v-show="config.bindIP"> <Col span="12"& ...
- ubuntu16.04 关闭系统的屏幕阅读功能
在安装audacity的时候,不知道点到哪里,电脑突然就不停的"Chinese Letter",后面仔细听,鼠标点到那里就会读那里文字,键盘输入也是,联想到Android上也有类似 ...
- vite+vue3 打包后页面空白现象
使用vite打包之后运行index.html空白,打开控制台发现报错: 解决方法: 在vite.config中加入: publicPath: './', 这是vite.config中的结构: ex ...
- 视野修炼第71期 | Rspack 家族新成员 Rsdoctor
欢迎来到第 71 期的[视野修炼 - 技术周刊],下面是本期的精选内容简 强烈推荐 Rspack 新成员:Rsdoctor Bun Shell DCloud:App跨平台框架对比2023版 开源工具& ...