仓酷云

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 487|回复: 6
打印 上一主题 下一主题

[学习教程] MYSQL编程:Spring 挪用ORACLE存储历程的了局集

[复制链接]
爱飞 该用户已被删除
跳转到指定楼层
楼主
发表于 2015-1-16 22:44:30 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
MySQL已经为支持所有最流行的Web2.0语言做好了准备,诸如Ruby、Ajax等,当然还有PHP。有的业界分析师说过,“每一个Web2.0公司实质上就是一个数据库公司。oracle|存储历程oracle关于初级特征老是不同凡响(我尽力厌恶这一点,假如利用它的产物就要对这类产物举行特定的编程,这也是我从不看好weblogic之类的平台的缘故原由),年夜工具存取一要定用它本人的LOB工具,所幸我还能经由过程LONGRAW来取代.以便能使程序不必要特定的编码.但关于存储历程(我是说前往了局集的存储历程),我还没有甚么办法能用一个通用的程序来处置ORACLE.太多的课本或文章在讲存储历程的挪用只是不卖力任地复杂实行一些涵数或无了局前往的存储历程,使年夜多半读者基本不晓得究竟怎样调么娲⒐痰慕峁?而在Spring中,基本就没有真正完整地先容对存储历程的了局集的处置,更别说象oracle这类"出格"的存储历程的了局集处置.
先来复杂看一下我们怎样在JDBC中处置存储历程的了局集的通用流程:
1.猎取CallableStatement语句:
CallableStatementcs=conn.prepareCall("{callspName(?,?,?)}");
2.传进输出参数和注册输入参数
cs.setXXX(index,value);//输出参数
cs.registerOutParameter(index,type);//输入参数
3.实行存储历程:
cs.execute();
关于一个存诸历程,假如前往的了局是我们事后晓得的,那末能够依据存储历程界说的按次来举行处置(现实上一样平常不会如许),但关于庞大的多了局集的处置,怎样界说一个通用的流程?
我们先看一下JDBC自己能为我们供应甚么?一个存储历程实行后前往的是boolean型:
booleanflag=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)
如今我们做一个轮回:
ResultSetrs=null;
intupdateCount=-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,以是通用的流程中你猎取不就任何了局:
packagePK_AREA_PUBLICis
TYPEserarch_resultISREFCURSOR;
PROCEDUREarea_search(vTarget_inINVARCHAR2,cur_result_outOUTserarch_result);
endPK_AREA_PUBLIC;
packagebodyPK_AREA_PUBLICis
PROCEDUREarea_search(vTarget_inINVARCHAR2,cur_result_outOUTserarch_result)
IS
sqlstrVARCHAR2(1000);
BEGIN
sqlstr:=select.................................;
OPENcur_result_outFORsqlstrUSINGvTarget_in;
ENDarea_search;
endPK_AREA_PUBLIC;

关于下面的例子,存储历程有一个输出参数,一个输入参数,我们要承受输入参数作为了局集处置.以是注册的时分应当注册为:
cs.registerOutParameter(2,oracle.jdbc.OracleTypes.CURSOR);//输入参数
如许在存储历程实行后,猎取输入数外型为ResultSet就能够处置:
ResultSetrs=(ResultSet)cs.getObject(2);
假如有多个了局集就用多个输入参数.

分明了ORACLE的特别性,我们再看看在spring中假如处置它的存储历程的了局集:
spring在处置庞大工具的时分,多数接纳回调的办法,请求程序员本人完成接口办法.也就是它供应了程序运转时的参数,请求你本人对这些参数举行处置.关于JdbcTemplate,它在良多中央供应了ResultSet参数供程序员处置.在Spring文档中供应了关于通用流程,也就是从存储历程实行了局中猎取了局集的
例程:
Mapout=execute(newHashMap());
实在它是默许完成了下面JDBC通用流程中对ResuleSet到Map的封装.而关于Oracle,我们就必需本人手完成对输入参数中ResultSet的回调:
publicclassSpringStoredProcedure
extendsStoredProcedure{
publicArrayList<HashMap>set=newArrayList<HashMap>();
//声明一个用于吸收了局集的数据布局,个中的元素为row,用map寄存
privateMapinParam;//输出参数
privateRowMapperrm=newRowMapper(){
publicObjectmapRow(ResultSetrs,introwNum)throwsSQLException{
returnnull;//不必从存储历程自己猎取了局
}
};
privateRowMapperResultReadercallback=newRowMapperResultReader(rm){
publicvoidprocessRow(ResultSetrs)//回调解理
throwsSQLException{
intcount=rs.getMetaData().getColumnCount();
String[]header=newString[count];
for(inti=0;i<count;i++)
header[i]=rs.getMetaData().getColumnName(i+1);
while(rs.next()){
HashMap<String,String>row=newHashMap(count+7);
for(inti=0;i<count;i++)
row.put(header[i],rs.getString(i+1));
set.add(row);
}
}
};//RowMapperResultReader作为输入参数的回调句柄
publicSpringStoredProcedure(DataSourceds,StringSQL){
setDataSource(ds);
setSql(SQL);
}
publicvoidsetOutParameter(Stringcolumn,inttype){
declareParameter(newSqlOutParameter(column,type,callback));
//使用回调句柄注册输入参数
}
publicvoidsetParameter(Stringcolumn,inttype){
declareParameter(newSqlParameter(column,type));
}
publicvoidSetInParam(MapinParam){
this.inParam=inParam;
}
publicMapexecute(){
compile();
returnexecute(this.inParam);
}
}
上面我们看一下挪用历程:

DriverManagerDataSourceds=.......;
SpringStoredProceduresp=newSpringStoredProcedure(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();
//传进输出参数值
Mapin=newHashMap();
in.put("vTarget_in","一个内容");
sp.SetInParam(in);
//实行存储历程
sp.execute();
Mapm=sp.set.get(0);//ReultSet的第一笔记录
//set界说为SpringStoredProcedure的属性用于吸收回调时的数据
//假如有多个输入参数,应当在每一个输入参数的回调办法中天生该输入
//参数对应的ArrayList,然后加到一个成员变量的数据布局中.
Iteratori=m.keySet().iterator();
while(i.hasNext()){
Stringkey=i.next().toString();
System.out.println(key+"=>"+m.get(key));
}
总之,下面的办法固然办理了Spring中对Oracle存储历程的挪用,但我尽力不保举这程庞大的处置
使用DBaaS能让收入损失从其他业务上得到弥补,如软件更新和硬件管理。也许决定走DBaaS之路的客户可能会跳过解决方案提供商,尽管这个决策看起来有点短视。
蒙在股里 该用户已被删除
沙发
发表于 2015-1-25 22:19:43 | 只看该作者
XML字段类型更好的解决了XML数据的操作。XQuery确实不错,但是个人对其没好感。(CSDN的开发者应该是相当的熟了!)
兰色精灵 该用户已被删除
板凳
发表于 2015-2-9 19:57:16 | 只看该作者
如果,某一版本可以提供强大的并发响应,但是没有Oracle的相应版本稳定,或者价格较贵,那么,它就是不适合的。
小妖女 该用户已被删除
地板
发表于 2015-2-27 19:49:41 | 只看该作者
语句级快照和事务级快照终于为SQLServer的并发性能带来了突破。个人感觉语句级快照大家应该应用。事务级快照,如果是高并发系统还要慎用。如果一个用户总是被提示修改不成功要求重试时,会杀人的!
深爱那片海 该用户已被删除
5#
发表于 2015-3-9 12:24:45 | 只看该作者
一个是把SQL语句写到客户端,可以使用DataSet进行加工;
小女巫 该用户已被删除
6#
发表于 2015-3-16 22:08:40 | 只看该作者
比如,MicrosoftSQLServer2008的某一个版本可以满足现在的这个业务的需要,而且价格还比Oracle11g要便宜,那么这一产品就是适合的。
乐观 该用户已被删除
7#
发表于 2015-3-23 04:13:50 | 只看该作者
另一个是把SQL语句写到服务器端,就是所谓的SP(存储过程);
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|仓酷云 鄂ICP备14007578号-2

GMT+8, 2024-5-21 14:18

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表