当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及两者相结合的实战 ...
随机推荐
- 【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 ...
- 学习ASP.NET Core Blazor编程系列文章之目录
学习ASP.NET Core Blazor编程系列一--综述 学习ASP.NET Core Blazor编程系列二--第一个Blazor应用程序(上) 学习ASP.NET Core Blazor编程系 ...
- JavaScript获取href的值
1.当href的值为正常网址时: <!DOCTYPE html> <html> <head> <title></title> <met ...
- Spring配置xml自定义事务管理器
上一篇博客讲解了Spring配置xml事务,使用的是Spring框架提供的事务管理器. 在本篇博文当中,来讲解一下使用自定义的事务管理方式. 把上一篇博文当中的这个配置 <bean id=&qu ...
- pollute 污染 pol=por=pro 向前 lut=释放 结合ps软件里面lut概念记忆
pollute 污染 pol = por = pro = 向前 lut = 释放 (ps里面有lut的概念) e 动词 向前释放 -> 污染 弄脏 简单记忆 poll / ute poll - ...
- python tkinter - pickle 持久化
查看当前python版本命令 cmd - python 现在当前版本是 3.8.8 tkinter - tool kits interface
- Navicat 通过 Http通道 连接远程 Mysql
https://jingyan.baidu.com/article/3d69c551aa54dff0cf02d7a0.html 注意本机ip填写 localhost
- 【LLM】在Colab上使用免费T4 GPU进行Chinese-Llama-2-7b-4bit推理
一.配置环境 1.打开colab,创建一个空白notebook,在[修改运行时环境]中选择15GB显存的T4 GPU. 2.pip安装依赖python包 !pip install --upgrade ...
- 基于ads1299的可穿戴脑电信号采集之性能调试总结
一 前言 问题背景: 最近做项目,遇到了一个问题,就是采集的信号有噪声,在这里做了很多尝试. 二 测试步骤 A 内部方波信号质量,通过测试发现内部方波信号质量特别好.这个说明了软件和存储这块,没啥 ...
- stable diffusion安装及使用
最近在看这个,踩了一些坑,现在有点头绪了,记录如下 安装很简单,直接git下载下来,然后进到根目录执行./web-ui.py,第一次启动你没有模型他会帮你下载个默认模型,我有模型了,就先把这个模型放到 ...