Spring 调用ORACLE存储过程的结果集

高云FPGA系列教程(4):片上逻辑分析仪GAO的使用 STM32等单片机,使用J-Link或ST-Link等调试器,可以进行在线调试,由于C代码是顺序执行的,我们可以插入断点,让程序停在我们需要的位置,或者是实时查看一些变量的数值,大大提高了我们Debug的速度,提高产品的开发效率。,连接到FPGA芯片的外部管脚上,如果想查看内部信号,还需要把这些信号定义成Output引出到外部管脚进行了测量,如果是多位数据,这样就会占用大量的管脚,但是此类工具有个优点就是支持多种协议解析,可以非常方便的查看协议的报文数据。当所有的仿真没问题了,才能进行最后一步:板级调试。 阅读详情

http://blog.youkuaiyun.com/sunsnow8/archive/2005/01/10/246588.aspx

oracle 对于高级特性总是与众不同(我极力讨厌这一点,如果使用它的产品就要对这种产品
进行特定的编程,这也是我从不看好weblogic之类的平台的原因),大对象存取一要定用它自己
的LOB对象,所幸我还能通过LONG RAW来代替.以便能使程序不需要特定的编码.但对于存储过程
(我是说返回结果集的存储过程),我还没有什么方法能用一个通用的程序来处理ORACLE.太多的
教材或文章在讲存储过程的调用只是不负责任地简单执行一些涵数或无结果返回的存储过程,
使大多数读者根本不知道到底如何调用存储过程的结果集.而在Spring中,根本就没有真正完全
地介绍对存储过程的结果集的处理,更别说象oracle这种"特别"的存储过程的结果集处理.

先来简单看一下我们如何在JDBC中处理存储过程的结果集的通用流程:

1.获取CallableStatement语句:

CallableStatement cs = conn.prepareCall("{call spName(?,?,?)}");

2.传入输入参数和注册输出参数

cs.setXXX(index,value);//输入参数
cs.registerOutParameter(index,type);//输出参数

3.执行存储过程:

cs.execute();

对于一个存诸过程,如果返回的结果是我们预先知道的,那么可以根据存储过程定义的顺序来进行
处理(事实上一般不会这样),但对于复杂的多结果集的处理,如何定义一个通用的流程?

我们先看一下JDBC本身能为我们提供什么?
一个存储过程执行后返回的是boolean型:
boolean flag = callableStatement.execute();
如果flag为true,那么说明返回了一个结果集(ResultSet)类型,你可以用getResultSet()得到当前行所在
的结果,而如果返回为flase,说明什么呢?

如果你不进行处理,什么也不能说明,只能说明当前指针不是ResultSet,有可能是更新计数(updateCount)
也可能什么也没有反因.

那么如果当前指针为flase时如何处理?我们应该先getUpdateCount();如果返回-1,既不是结果集,又
不是更新计数了.说明没的返回了.而如果getUpdateCount()返回0或大于0,则说明当前指针是更新计数(
0的时候有可能是DDL指令).无论是返回结果集或是更新计数,那么则可能还继续有其它返回.只有在当前
指指针getResultSet()==null && getUpdateCount() == -1才说明没有再多的返回.

存储过程的返回和ResultSet类似,每次处理的返回结果相当于是ResultSet的Row,只不过存储过程的Row
最先在第一行而不是象ResultSet要先next才到第一行,存储过程向下移动一行用getMoreResults(),相
当于ResultSet的next().同样它返回boolean和上面的flag一样,只是说明当前行是不是ResultSet,如果是
flase,你还是要判断是不是updateCount,在每一行,都要先同时判断是否为ResultSet还是UpdateCount,如
果是其中一种则要继续getMoreResults(),当不是ResultSet也不是updateCount时,说明没有返回结果了,
这时再获取输出参数.

看明白了吗?

那我们就根据上面的规则来写一个通用的流程吧:

首先,我们要确定什么时候没说结果集了:
if(cs.getResultSet() == null && cs.getUpdateCount() == -1)
现在我们做一个循环:
ResultSet rs = null;
int updateCount = -1;
flag = cs.execute();
do{
    updateCount = cs.getUpdateCount();
    if(updateCount != -1){//说明当前行是一个更新计数
        //处理.
        cs.getMoreResults();
        continue;//已经是更新计数了,处理完成后应该移动到下一行
             //不再判断是否是ResultSet
    }
    rs = cs.getResultSet();
    if(rs != null){//如果到了这里,说明updateCount == -1
        //处理rs
        cs.getMoreResults();
        continue;
            //是结果集,处理完成后应该移动到下一行
    }
    //如果到了这里,说明updateCount == -1 && rs == null,什么也没的了
   
}while(!(updateCount == -1 && rs == null));
cs.getXXX(int);//获取输出参数


以上是对于通用的存储过程返回的结果集的处理,而oracle,它不能返回结果集,只能在输出参数中
返回一个cursor,所以通用的流程中你获取不到任何结果:

package PK_AREA_PUBLIC is
  TYPE serarch_result IS REF CURSOR;
  PROCEDURE  area_search(vTarget_in IN VARCHAR2 ,cur_result_out OUT serarch_result) ;
end PK_AREA_PUBLIC;

package body PK_AREA_PUBLIC is
  PROCEDURE  area_search(vTarget_in IN VARCHAR2 ,cur_result_out OUT serarch_result)
  IS
  sqlstr VARCHAR2(1000);
  BEGIN
       sqlstr:='select .................................';
       OPEN cur_result_out FOR sqlstr USING vTarget_in;
  END area_search;
end PK_AREA_PUBLIC;


对于上面的例子,存储过程有一个输入参数,一个输出参数,我们要接受输出参数作为结果集处理.所
以注册的时候应该注册为:

cs.registerOutParameter(2,oracle.jdbc.OracleTypes.CURSOR);//输出参数

这样在存储过程执行后,获取输出数造型为ResultSet就可以处理:

ResultSet rs = (ResultSet)cs.getObject(2);

如果有多个结果集就用多个输出参数.


明白了ORACLE的特殊性,我们再看看在spring中如果处理它的存储过程的结果集:
spring在处理复杂对象的时候,大都采用回调的方法,要求程序员自己实现接口方法.也就是它提供了
程序运行时的参数,要求你自己对这些参数进行处理.对于JdbcTemplate,它在很多地方提供了ResultSet
参数供程序员处理.在Spring文档中提供了对于通用流程,也就是从存储过程执行结果中获取结果集的
例程:

Map out = execute(new HashMap());
其实它是默认实现了上面JDBC通用流程中对ResuleSet到Map的封装.而对于Oracle,我们就必须自己手
实现对输出参数中ResultSet的回调:

public class SpringStoredProcedure
    extends StoredProcedure {
  public ArrayList<HashMap> set = new ArrayList<HashMap>();
  //声明一个用于接收结果集的数据结构,其中的元素为row,用map存放

  private Map inParam;//输入参数
  private RowMapper rm = new RowMapper(){
    public Object mapRow(ResultSet rs,int rowNum) throws SQLException{
      return null;//不用从存储过程本身获取结果
    }
  };

  private RowMapperResultReader callback = new RowMapperResultReader(rm ){
    public void processRow(ResultSet rs) //回调处理
                throws SQLException{
      int count = rs.getMetaData().getColumnCount();
      String[] header = new String[count];
      for(int i=0;i<count;i++)
        header[i] = rs.getMetaData().getColumnName(i+1);
      while(rs.next()){
        HashMap<String,String> row = new HashMap(count+7);
        for(int i=0;i<count;i++)
          row.put(header[i],rs.getString(i+1));
        set.add(row);
      }
    }
  }; //RowMapperResultReader作为输出参数的回调句柄
  public SpringStoredProcedure(DataSource ds, String SQL) {
    setDataSource(ds);
    setSql(SQL);
  }

  public void setOutParameter(String column,int type){
    declareParameter(new SqlOutParameter(column, type,callback));
    //利用回调句柄注册输出参数
  }
  public void setParameter(String column,int type){
    declareParameter(new SqlParameter(column, type));
  }
 
  public void SetInParam(Map inParam){
    this.inParam = inParam;
  }

  public Map execute() {
    compile();
    return execute(this.inParam);
  }
}

下面我们看一下调用过程:

   
    DriverManagerDataSource ds = .......;

    SpringStoredProcedure sp = new SpringStoredProcedure(ds,"PK_AREA_PUBLIC.area_search");
   
    //注册参数类型,输入参数和输出参数同时注册,否则不能正确编译存储过程
    sp.setParameter("vTarget_in",java.sql.Types.VARCHAR);
    sp.setOutParameter("cur_result_out",oracle.jdbc.OracleTypes.CURSOR);
    sp.compile();
   
    //传入输入参数值
    Map in = new HashMap();
    in.put("vTarget_in","一个内容");
    sp.SetInParam(in);
   
    //执行存储过程
    sp.execute();

    Map m = sp.set.get(0);//ReultSet的第一条记录
     //set定义为SpringStoredProcedure的属性用于接收回调时的数据
     //如果有多个输出参数,应该在每个输出参数的回调方法中生成该输出
     //参数对应的ArrayList,然后加到一个成员变量的数据结构中.
    Iterator i = m.keySet().iterator();
    while(i.hasNext()){
      String key = i.next().toString();
      System.out.println(key + "=>" + m.get(key));
    }

  总之,上面的方法虽然解决了Spring中对Oracle存储过程的调用,但我极力不推荐这程复杂的处理

2025年广东省职业院校技能大赛高职组“区块链技术应用”正式赛题解析答案(标准答案参阅) 某公司规划开发一个区块链供应链金融平台,包括核心企业、供应商、银行等角色,通过智能合约代码逐步构建区块链供应链金融平台的基本功能,实现银行向核心企业提供授信并发行数字凭证,企业与企业之间转让数字凭证。此外需要完成区块链供应链金融平台的前后端,实现基本的业务逻辑 阅读详情

相关推荐

MATLAB Appdesigner开发独立桌面App全流程(一):以打开串口功能为例介绍Appdesigner的基本使用

本文详细介绍了Appdesigner的基本使用,以串口功能为例介绍按钮回调函数的实现以及控件之间通信的问题

Zhuwany的博客 3万+

spring调用Oracle存储过程,并返回结果集的完整实例

这是总结以前使用spring调用Oracle存储过程,并用cursor返回结果集的一个完整实例,希望能对大家有帮助。 1. 创建表: 代码 create table TEST_USERS     (       USER_ID  VARCHAR2(10) not null,       NAME     VARCHAR2(10) no

鸟儿飞的专栏 1892

【LLC快速上手系列】LLC轻载时,死区时间怎么调才对?别再傻傻乱搞了!

死区时间,就是指。如果你死区设得好,就能让开通前 ( V_DS to 0 ),完美实现!

weixin_43199439的博客 1856

spring调用oracle的存储过程

JdbcTemplate jt = new JdbcTemplate(dataSource); //System.out.println("修改角色"); String sql = "{call Proc_BatchUpdateRd_Role(?,?,?,?,?,?,?)}"

想离开水的鱼 553

AutoJs调用DeepSeek大模型接口实战教程 AutoJs接入DeepSeek、 DeepSeek API调用 、 手机脚本接入大模型

通过这篇文章,我们用 AutoJs 成功接入了 DeepSeek Chat API。使用发送请求在 Header 里正确携带 API Key从里拿到最终返回结果这样一来,你就可以在 AutoJs 里实现一个智能助手脚本,甚至做更复杂的 AI 自动化工具。

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 468

HITECH海泰克触摸屏如何使用串口进行程序的下载和上传(拨码设置)以及离散量报警相关设定?

HITECH海泰克触摸屏如何使用串口进行程序的下载和上传(拨码设置)以及离散量报警相关设定? 首先,我们进行触摸屏一侧的设置,如下图所示: 触摸屏背后有拨码开关,当我们需要上传或下载程序时,需要将7#开关拨到上面; 左侧是DC24V电源接口; 下方是COM1、COM2和COM3通信端口,选择我们需要的端口后,插上通信电缆,拔掉24V电源,然后重新上电; 然后,屏幕会进入如下图所示界面,此时显示当前选择的端口为COM2,我们点击F2“config”,进入设置界面, 可以看到COM2端口是“Enabled”

Robot_PLC_HMI_Automation 3万+

SpringJDBC调用oracle存储过程的方法

第一种方法:public Map paymentCheckTenpay(final Map maps) {// TODO Auto-generated method stubMap resultMaps = (Map) this.getJdbcTemplate().execute(new CallableStatementCreator() {@Overridepublic C

口袋里的小龙的专栏 2409

使用Simulink对氢燃料电池与锂电池的混合储能系统进行建模

本文介绍了基于Simulink的氢燃料电池与锂电池混合储能系统建模与协同控制方法。系统通过氢燃料电池提供稳定能源,锂电池实现快速响应,结合DC-DC变换器和负载管理器实现动态调控。详细阐述了从模型创建、关键模块配置到控制器设计的完整流程,重点说明了功率分配算法和充放电控制策略的实现。通过仿真分析验证了系统在不同负载条件下的性能表现,包括响应速度、工作效率和稳定性等指标。该方案为新能源混合储能系统的设计与优化提供了实用指导,有助于提升系统可靠性和延长电池寿命。

amy_mhd的博客 314

SSM(MyBatis+Spring+SpringMVC)Oracle存储过程应用实战

      存储过程可以让我们的数据库操作的效率变高,因为存储过程是提前编译好了。不同于我们发送一条SQL,每次都需要经历系列步骤(语法检查——语义分析——编译——缓存——执行),使用存储过程的话直接就是执行编译好的内容,这样有利于提升系统的性能,尤其是在高并发的情况下这样的效果应该是最为明显的。那么接下来我就分享一下我是如何使用Oracle的存储过程的吧!...

muzi木子 583

写给开发人员的实用密码学 - Hash算法

说到Hash(哈希),开发人员应该不陌生,比如Hash表是一种非常常用的数据结构,通过Hash表能够根据键值快速找到数据。哈希函数将文本(或其他数据)映射为整数,从而能够提高检索效率。密...

云水木石 1503

042_小驰私房菜_MTK Camera yuv旋转90度方案

做旋转可以在app层接收到数据后,自行做旋转,也可以在hal层,针对yuv format这路流进行旋转。那我们做旋转也可以采用类似的方式。预览和录像是正常的,这个是因为预览和录像有方向相关属性可以调整,系统会根据摄像头mount的角度已经当前设备的方向,进行对应的旋转。这个下面这个文件,可以修改摄像头的mount角度。,可以看到前摄的Orientation是270,所以原始出图是做了90度的旋转。这个方案,思路就是在配流信息中,将rotation信息进行修改。注:本文章所用权归:小驰成长圈,禁止转载宣传!

587

Spring 调用ORACLE存储过程的结果集(转)

oracle 对于高级特性总是与众不同(我极力讨厌这一点,如果使用它的产品就要对这种产品进行特定的编程,这也是我从不看好weblogic之类的平台的原因),大对象存取一要定用它自己的LOB对象,所幸我还能通过LONG RAW来代替.以便能使程序不需要特定的编码.但对于存储过程(我是说返回结果集的存储过程),我还没有什么方法能用一个通用的程序来处理ORACLE.太多的教材或文章在讲存储过程的调用只是

843

TriCore架构-如何将系统刷成HSM

本文介绍了芯片刷写操作流程:首先加载project_Merge.s19文件,进入UCB界面展开BMHD0_ORIG和BMHD1_ORIG。重点说明需要将STAD地址从原始值A0000000修改为0XA00A0000,并详细描述了编辑、更新和写入芯片的步骤。最后提示在HSM刷写过程中如遇错误可能需要输入密码。该操作涉及关键地址修改,需谨慎执行。

xiandang8023的博客 95

Spring 调用Oracle存储过程的结果集

oracle 对于高级特性总是与众不同(我极力讨厌这一点,如果使用它的产品就要对这种产品进行特定的编程,这也是我从不看好weblogic之类的平台的原因),大对象存取一要定用它自己的LOB对象,所幸我还能通过LONG RAW来代替。以便能使程序不需要特定的编码。但对于存储过程(我是说返回结果集的存储过程),我还没有什么方法能用一个通用的程序来处理ORACLE。太多的教材或文章在讲存储过程的调用只是

jenny537的专栏 433

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Spring调用ORACLE存储过程的结果集

Spring调用ORACLE存储过程的结果集2006-08-24 15:12 oracle 对于高级特性总是与众不同(我极力讨厌这一点,如果使用它的产品就要对这种产品进行特定的编程,这也是我从不看好weblogic之类的平台的原因),大对象存取一要定用它自己的LOB对象,所幸我

Opossum的专栏 1293

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

上一篇: SQL语句导入导出大全
下一篇: 共享打印机不能使用
tiny_yan
博客等级 码龄26年 3粉丝 4原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值