|
我们知道,ORACLE存储过程(以下简称SP)本身连单结果集都不能返回,只能通过输出参数返回cursor引用.对于一次查询多个结果集,则要注册多个输出参数.
但是很多时候我们并不知道一次查询要返回多少个结果集.而ORACLE的SP又不支持变长参数,如果一次从十多个表中查询结果集,则客户端要和服务端交互十几次,这是一个极大的浪费.我在一个新项目的有需要根据一个ID去十多个表中取相应数据的需求.于是采用了职下方案:
用java写SP,这一点,并不是我看不起PL/SQL,JAVA的运算能力绝对比PL/SQL强N倍,比竟它是一门非常完善的编程语言,用它写SP可以做你想做的任何事.而且用JAVA写SP调试非常方便:
public class SPClass{ public static String test(){return "hello!";}//必须是静态方法 }
这样一个java文件或类或多个jar文件可以非常方便地用loadjava命令加载到oracle数据库中,然后只要
create or replace function [procedure] test return varchar2 as language java name 'SPClass.test() return java.lang.String'; 就可以加载这个过程或函数. 关键是你create一个function[procedure]后,如果你想修改它你只要修改源文件并重新用 loadjava命令回载到数据库中,而不需要再在SQLPLUS环境下重新create or replace function [procedure] ,非常的方便.
基于上面的应用,我在JAVA方法中根据输入的参数,用ORACLE内置的连结获取数据后封装在 OracleCachedRowSet中,然后多个OracleCachedRowSet以参数传入的表名为key,放在一个HashMap中,将这个 HashMap序列化后base64编码,返回成String. 这样客户端获取base64字符串后decode成byte[] 返序列化成HashMap,然后根据传入的表名获取相应的OracleCachedRowSet,一次交互可以获取到多个结果集:
import oracle.jdbc.driver.*; import oracle.jdbc.rowset.*; import java.sql.*; import java.util.*; import java.io.*;
/** * <p>Title: </p> * * <p>Description: </p> * * <p>Copyright: Copyright (c) 2005</p> * * <p>Company: </p> * * @author not attributable * @version 1.0 */ public class MultiResultSet { public static String getMultiResultSet(String args,String multiType,int page) throws SQLException { try{ String[] params = split(args,","); HashMap rt = new HashMap(); for(int i=0;i<params.length;i++){ OracleCachedRowSet rowset = new OracleCachedRowSet(); rowset.setUrl("jdbc:default:connection"); // rowset.setUsername(""); // rowset.setPassword(""); String sql = "select * from " + params[i] ; rowset.setCommand(sql); rowset.execute(); rt.put(params[i],rowset.createCopy()); } ByteArrayOutputStream ba = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(ba); out.writeObject(rt); byte[] buf = ba.toByteArray(); out.flush(); out.close(); return new sun.misc.BASE64Encoder().encode(buf); } catch(Exception e){ return e.getMessage(); } } public static String[] split(String strOb, String mark) { if (strOb == null) { return null; } StringTokenizer st = new StringTokenizer(strOb, mark); ArrayList tmp = new ArrayList(); while (st.hasMoreTokens()) { tmp.add(st.nextToken()); } String[] strArr = new String[tmp.size()]; for (int i = 0; i < tmp.size(); i++) { strArr[i] = (String) tmp.get(i); } return strArr; } }
客户机器测试:
import java.io.ByteArrayInputStream; import java.io.ObjectInputStream; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.Types; import java.util.HashMap; import java.util.Iterator;
import sun.misc.BASE64Decoder;
/** * <P>Title:</P> * <P>Description:</P> * @author : cheung * @version : 1.0 * @date : 2005-4-28 * @homepage : <a href="http://www.zhanglihai.com" target="_blank">ZhangLiHai.Com </a> * @email : <a href="mailto:zhanglihai.com@gmail.com">zhanglihai.com@gmail.com </a> */ public class ResultSetTest { /** * */ public ResultSetTest() { super(); } public void test() { long startTime = System.currentTimeMillis(); Connection con = null; try { con = getConnection(); CallableStatement cs = con.prepareCall("{? = call GetTest(?,?,?)}"); cs.registerOutParameter(1, Types.VARCHAR); cs.setString(2, "copyright,filetype"); cs.setString(3, "test"); cs.setInt(4, 1); cs.execute(); String temps = cs.getString(1); // System.out.println(temps); byte[] buf = new BASE64Decoder().decodeBuffer(temps); ObjectInputStream input = new ObjectInputStream(new ByteArrayInputStream(buf)); HashMap map = (HashMap) input.readObject(); Iterator keys = map.keySet().iterator(); Object key = null; oracle.jdbc.rowset.OracleCachedRowSet value = null; while (keys.hasNext()) { key = keys.next(); System.out.println("key : " + key + " value : " + map.get(key)); } System.out.println("usedTime : " + (System.currentTimeMillis() - startTime) + " ms."); } catch (Exception ex) { ex.printStackTrace(System.out); } finally { try { con.close(); } catch (Exception ex) { } } } public Connection getConnection() throws Exception { //构造你的Connection,或者用DataSource来实现 return con; } public static void main(String[] args) { ResultSetTest test = new ResultSetTest(); test.test(); } }
以上方案在台式机上测试,取两个表,记录都在五百多条左右.时间在60-120ms之间.这种方案适用于根据某一ID获取不同表中数据,但数据量不大,如果数据量很大,上万条记录最好不要用CachedRowSet.
转载:http://www.cnjbb.org/thread.jsp?boardid=23&threadid=44518&pageno=last#lastpost
|