`
fly1206
  • 浏览: 56936 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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

阅读更多
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时,说明没有返回结果了,这时再获取输出参数。
www.bitsCN.com


  
  看明白了吗?
  
  那我们就根据上面的规则来写一个通用的流程吧:
  
  首先,我们要确定什么时候没说结果集了:
  
  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)); bbs.bitsCN.com
  
  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);//输出参数 bitsCN.nET中国网管博客
  
  这样在存储过程执行后,获取输出数造型为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); www_bitscn_com
  
  sp.setOutParameter("cur_result_out",oracle.jdbc.OracleTypes.CURSOR);
  
  sp.compile();
  
  //传入输入参数值
  
  Map in = new HashMap();
  
  in.put("vTarget_in","一个内容");
  
  sp


分享到:
评论

相关推荐

    知识小集微信小程序

    4. **API调用**:微信小程序提供了丰富的API接口,如网络请求、本地存储、地图、多媒体、位置服务等。开发者需要熟悉这些API的使用,以实现各种功能。 5. **生命周期理解**:理解微信小程序中页面和组件的生命周期...

    PLSQL_Developer9.0使用技巧

    在使用 PL/SQL Developer 操作 Oracle 时,有时候调用某些存储过程,或者调试存储过程;调用存储过程的方法:首先,在 PL/SQL Developer 左边的 Browser 中选择 Procedures,查找需要调用的存储过程;然后,选中调试...

    DWR 实用例子小集

    它通过一个名为`dwr.engine`的对象在浏览器中提供服务,允许JavaScript调用服务器端的Java方法,并将结果返回到前端。DWR支持异步通信,使得页面无需刷新就能更新数据,提升了用户体验。 **2. 安装与配置DWR** 首先...

    java调用webservice最精简的jar包

    6. **依赖注入框架**:在某些情况下,如果Web服务调用需要依赖注入,如Spring框架,那么`spring-context.jar`和`spring-beans.jar`等Spring核心库也是必不可少的。 7. **SSL支持**:对于安全的HTTPS连接,需要`...

    GAS汇编指令小集html格式

    GAS汇编指令小集GAS汇编指令小集GAS汇编指令小集GAS汇编指令小集GAS汇编指令小集GAS汇编指令小集GAS汇编指令小集

    基于spring,struts(struts2),hibernate的web项目脚手架

    并简单扩展显示pageNumber 集成DBUnit及spring对数据库测试的支持 内置的分页查询PageInfo接口 Java日期转换的特殊处理,与My97DatePicker集成 内置最精简的ant构建脚本,简单修改即可使用 公共类库友好的包名java...

    知识小集微信小程序.zip

    【标题】"知识小集微信小程序.zip"是一个包含微信小程序源码的压缩文件,它旨在为开发者提供一个简单、易用且便于学习交流的平台。这个小程序可能包含了各种功能模块,便于用户快速理解和实践微信小程序的开发。 ...

    Oracle_win32_11gR1_database出错误及解决办法

    Oracle新手使用常见错误小集,1、ORA-12541:TNS:没有监听器。2、ORA-12500:TNS:监听程序无法启动专用服务器进程或ORA-12560:TNS:协议适配器错误。 3、如果数据库服务启动失败,则很有可能是其注册表项值损坏。。。4...

    C#.net面试小集

    ### C#.NET 面试知识点详解 ...- **序列化**:将对象的状态转换为可以存储或传输的形式的过程。 以上知识点涵盖了C#.NET开发中的常见概念和技术要点,对于准备面试的人来说是非常有价值的复习资料。

    FreeRTOS资料小集.CHM

    FreeRTOS资料小集.CHM

    经典java类书籍小集

    【标题】"经典java类书籍小集"所涵盖的知识点主要集中在Java编程语言的学习和进阶上。这个压缩包很可能是包含了一些Java编程的经典书籍章节或者摘要,旨在帮助学习者深入理解和掌握Java语言的核心概念、设计模式以及...

    对联基础知识小集.pdf

    对联基础知识小集.pdf

    ISO9000国家注册审核员考试试题小集.pdf

    本文档为ISO9000国家注册审核员考试试题小集,涵盖了质量管理、统计技术、过程控制、质量控制等方面的知识点。 1. 统计技术:本部分考查统计技术的基本概念和方法,包括实验设计、假设检验、回归分析、计数型抽样...

    swift-iOS知识小集

    "swift-iOS知识小集"旨在将这些碎片化的信息整合起来,方便开发者快速学习和回顾。以下是一些可能包含在该压缩包中的知识点: 1. **枚举与关联值**:Swift中的枚举不仅限于定义一组相关的常量,还能关联各种类型的...

    C语言的错误小集 C语言的错误

    例如,在表达式 `a = b + c * d` 中,如果不使用括号明确先进行乘法运算还是加法运算,则可能导致意外的结果。 #### 2. 模糊的符号(Ambiguous symbol) 当一个标识符可能被解释为多种类型时,就出现了模糊的符号...

    java面试问题小集

    【Java面试问题小集】 1. **String 与 StringBuffer 的区别** String 是不可变对象,每次修改都会创建新的对象,而 StringBuffer 是可变对象,修改时不会创建新对象,因此在频繁修改字符串的情况下,使用 ...

    数学建模资料——论文小集

    《数学建模资料——论文小集》是一份珍贵的资源,包含了丰富的数学建模知识,特别是其中涵盖了美国赛特等奖及一等奖的论文。数学建模是应用数学解决实际问题的重要方法,它涉及到数学、计算机科学、工程学以及社会...

    最新浪漫温馨短信小集.doc

    最新浪漫温馨短信小集.doc

    【CSDN首发】FreeRTOS资料小集

    这个资料小集包含了对FreeRTOS深入理解的关键信息,非常适合初学者和有经验的开发者作为参考。 首先,让我们从FreeRTOS的核心概念开始。FreeRTOS是一个实时操作系统(RTOS),它的核心在于调度算法,比如基于优先级...

    小学一年级期末教师评语小集.pdf

    小学一年级期末教师评语小集.pdf

Global site tag (gtag.js) - Google Analytics