JAVA网页编程之Java 挪用存储历程
windows系统样,他们做了什么事或者留了一些后门程序,谁都不知道,二,java开发是跨平台,任何系统上都可以运行,对于保密型系统和大型系统开发这是必要的存储历程本文论述了怎样利用DBMS存储历程。我论述了利用存储历程的基础的和初级特征,好比前往ResultSet。本文假定你对DBMS和JDBC已十分熟习,也假定你可以毫无停滞地浏览别的言语写成的代码(即不是Java的言语),可是,其实不请求你有任何存储历程的编程履历。存储历程是指保留在数据库并在数据库端实行的程序。你可使用特别的语法在Java类中挪用存储历程。在挪用时,存储历程的称号及指定的参数经由过程JDBC毗连发送给DBMS,实行存储历程并经由过程毗连(假如有)前往了局。
利用存储历程具有和利用基于EJB或CORBA如许的使用服务器一样的优点。区分是存储历程能够从良多盛行的DBMS中无偿使用,而使用服务器多数十分高贵。这其实不只是允许证用度的成绩。利用使用服务器所必要消费的办理、编写代码的用度,和客户程序所增添的庞大性,都能够经由过程DBMS中的存储历程所全部地替换。
你可使用Java,Python,Perl或C编写存储历程,可是一般利用你的DBMS所指定的特定言语。Oracle利用PL/SQL,PostgreSQL利用pl/pgsql,DB2利用ProceduralSQL。这些言语都十分类似。在它们之间移植存储历程其实不比在Sun的EJB标准分歧完成版本之间移植SessionBean坚苦。而且,存储历程是为嵌进SQL所计划,这使得它们比Java或C等言语加倍友爱中央式表达数据库的机制。
由于存储历程运转在DBMS本身,这能够匡助削减使用程序中的守候工夫。不是在Java代码中实行4个或5个SQL语句,而只必要在服务器端实行1个存储历程。收集上的数据往复次数的削减能够戏剧性地优化功能。
利用存储历程
复杂的老的JDBC经由过程CallableStatement类撑持存储历程的挪用。该类实践上是PreparedStatement的一个子类。假定我们有一个poets数据库。数据库中有一个设置墨客去世岁数的存储历程。上面是对老酒鬼DylanThomas(oldsoakDylanThomas,不指定是不是有关典故、文明,请品评斧正。译注)举行挪用的具体代码:
try{
intage=39;
StringpoetName="dylanthomas";
CallableStatementproc=connection.prepareCall("{callset_death_age(?,?)}");
proc.setString(1,poetName);
proc.setInt(2,age);
cs.execute();
}catch(SQLExceptione){//....}
传给prepareCall办法的字串是存储历程挪用的誊写标准。它指定了存储历程的称号,?代表了你必要指定的参数。
和JDBC集成是存储历程的一个很年夜的便当:为了从使用中挪用存储历程,不必要存根(stub)类大概设置文件,除你的DBMS的JDBC驱动程序外甚么也不必要。
当这段代码实行时,数据库的存储历程就被挪用。我们没有往猎取了局,由于该存储历程其实不前往了局。实行乐成或失利将经由过程破例得知。失利大概意味着挪用存储历程时的失利(好比供应的一个参数的范例不准确),大概一个使用程序的失利(好比抛出一个破例唆使在poets数据库中其实不存在“DylanThomas”)
分离SQL操纵与存储历程
映照Java对象到SQL表中的行相称复杂,可是一般必要实行几个SQL语句;多是一个SELECT查找ID,然后一个INSERT拔出指定ID的数据。在高度规格化(切合更高的范式,译注)的数据库形式中,大概必要多个表的更新,因而必要更多的语句。Java代码会很快地收缩,每个语句的收集开支也敏捷增添。
将这些SQL语句转移到一个存储过程当中将年夜年夜简化代码,仅触及一次收集挪用。一切联系关系的SQL操纵都能够在数据库外部产生。而且,存储历程言语,比方PL/SQL,同意利用SQL语法,这比Java代码加倍天然。上面是我们初期的存储历程,利用Oracle的PL/SQL言语编写:
createprocedureset_death_age(poetVARCHAR2,poet_ageNUMBER)
poet_idNUMBER;
beginSELECTidINTOpoet_idFROMpoetsWHEREname=poet;
INSERTINTOdeaths(mort_id,age)VALUES(poet_id,poet_age);
endset_death_age;
很共同?不。我赌博你必定等候看到一个poets表上的UPDATE。这也表示了利用存储历程完成是何等简单的一件事变。set_death_age几近能够一定是一个很烂的完成。我们应当在poets表中增加一列来存储去世岁数。Java代码中其实不体贴数据库形式是怎样完成的,由于它仅挪用存储历程。我们今后能够改动数据库形式以进步功能,可是我们不用修正我们代码。
上面是挪用下面存储历程的Java代码:
publicstaticvoidsetDeathAge(PoetdyingBard,intage)throwsSQLException{
Connectioncon=null;
CallableStatementproc=null;
try{
con=connectionPool.getConnection();
proc=con.prepareCall("{callset_death_age(?,?)}");
proc.setString(1,dyingBard.getName());
proc.setInt(2,age);
proc.execute();
}
finally{
try{proc.close();}
catch(SQLExceptione){}
con.close();
}
}
为了确保可保护性,倡议利用像这儿如许的static办法。这也使得挪用存储历程的代码会合在一个复杂的模版代码中。假如你用到很多存储历程,就会发明仅必要拷贝、粘贴就能够创立新的办法。由于代码的模版化,乃至也能够经由过程剧本主动临盆挪用存储历程的代码。
Functions
存储历程能够有前往值,以是CallableStatement类有相似getResultSet如许的办法来猎取前往值。当存储历程前往一个值时,你必需利用registerOutParameter办法告知JDBC驱动器该值的SQL范例是甚么。你也必需调剂存储历程挪用来唆使该历程前往一个值。
上面接着下面的例子。此次我们查询DylanThomas去世时的岁数。此次的存储历程利用PostgreSQL的pl/pgsql:
createfunctionsnuffed_it_when(VARCHAR)returnsintegerdeclare
poet_idNUMBER;
poet_ageNUMBER;
begin
--firstgettheidassociatedwiththepoet.
SELECTidINTOpoet_idFROMpoetsWHEREname=$1;
--getandreturntheage.
SELECTageINTOpoet_ageFROMdeathsWHEREmort_id=poet_id;
returnage;
end;languagepl/pgsql;
别的,注重pl/pgsql参数名经由过程Unix和DOS剧本的$n语法援用。同时,也注重嵌进的正文,这是和Java代码比拟的另外一个优胜性。在Java中写如许的正文固然是能够的,可是看起来很混乱,而且和SQL语句摆脱,必需嵌进到JavaString中。
上面是挪用这个存储历程的Java代码:
connection.setAutoCommit(false);
CallableStatementproc=connection.prepareCall("{?=callsnuffed_it_when(?)}");
proc.registerOutParameter(1,Types.INTEGER);
proc.setString(2,poetName);
cs.execute();
intage=proc.getInt(2);
假如指定了毛病的前往值范例会如何?那末,当挪用存储历程时将抛出一个RuntimeException,正如你在ResultSet操纵中利用了一个毛病的范例所碰着的一样。
庞大的前往值
关于存储历程的常识,良多人仿佛就熟习我们所会商的这些。假如这是存储历程的全体功效,那末存储历程就不是别的远程实行机制的交换计划了。存储历程的功效比这壮大很多。
当你实行一个SQL查询时,DBMS创立一个叫做cursor(游标)的数据库对象,用于在前往了局中迭代每行。ResultSet是以后工夫点的游标的一个暗示。这就是为何没有缓存大概特定命据库的撑持,你只能在ResultSet中向前挪动。
某些DBMS同意从存储过程当中前往游标的一个援用。JDBC其实不撑持这个功效,可是Oracle、PostgreSQL和DB2的JDBC驱动器都撑持在ResultSet上翻开到游标的指针(pointer)。
假想列出一切没有活到退休岁数的墨客,上面是完成这个功效的存储历程,前往一个翻开的游标,一样也利用PostgreSQL的pl/pgsql言语:
createprocedurelist_early_deaths()returnrefcursorasdeclare
toesuprefcursor;
begin
opentoesupforSELECTpoets.name,deaths.ageFROMpoets,deaths--allentriesindeathsareforpoets.--butthetablemightbecomegeneric.
WHEREpoets.id=deaths.mort_idANDdeaths.age<60;
returntoesup;
end;languageplpgsql;
上面是挪用该存储历程的Java办法,将了局输入到PrintWriter:
PrintWriter:
staticvoidsendEarlyDeaths(PrintWriterout){
Connectioncon=null;
CallableStatementtoesUp=null;
try{
con=ConnectionPool.getConnection();
//PostgreSQLneedsatransactiontodothis...con.
setAutoCommit(false);//Setupthecall.
CallableStatementtoesUp=connection.prepareCall("{?=calllist_early_deaths()}");
toesUp.registerOutParameter(1,Types.OTHER);
toesUp.execute();
ResultSetrs=(ResultSet)toesUp.getObject(1);
while(rs.next()){
Stringname=rs.getString(1);
intage=rs.getInt(2);
out.println(name+"was"+age+"yearsold.");
}
rs.close();
}
catch(SQLExceptione){//Weshouldprotectthesecalls.toesUp.close();con.close();
}
}
由于JDBC其实不间接撑持从存储过程当中前往游标,我们利用Types.OTHER来唆使存储历程的前往范例,然后挪用getObject()办法并对前往值举行强迫范例转换。
这个挪用存储历程的Java办法是mapping的一个好例子。Mapping是对一个集上的操纵举行笼统的办法。不是在这个历程上前往一个集,我们能够把操纵传送出来实行。本例中,操纵就是把ResultSet打印到一个输入流。这是一个值得举例的很经常使用的例子,上面是挪用统一个存储历程的别的一个办法完成:
publicclassProcessPoetDeaths{
publicabstractvoidsendDeath(Stringname,intage);
}
staticvoidmapEarlyDeaths(ProcessPoetDeathsmapper){
Connectioncon=null;
CallableStatementtoesUp=null;
try{
con=ConnectionPool.getConnection();
con.setAutoCommit(false);
CallableStatementtoesUp=connection.prepareCall("{?=calllist_early_deaths()}");
toesUp.registerOutParameter(1,Types.OTHER);
toesUp.execute();
ResultSetrs=(ResultSet)toesUp.getObject(1);
while(rs.next()){
Stringname=rs.getString(1);
intage=rs.getInt(2);
mapper.sendDeath(name,age);
}
rs.close();
}catch(SQLExceptione){//Weshouldprotectthesecalls.toesUp.close();
con.close();
}
}
这同意在ResultSet数据上实行恣意的处置,而不必要改动大概复制猎取ResultSet的办法:
staticvoidsendEarlyDeaths(finalPrintWriterout){
ProcessPoetDeathsmyMapper=newProcessPoetDeaths(){
publicvoidsendDeath(Stringname,intage){
out.println(name+"was"+age+"yearsold.");
}
};
mapEarlyDeaths(myMapper);
}
这个办法利用ProcessPoetDeaths的一个匿名实例挪用mapEarlyDeaths。该实例具有sendDeath办法的一个完成,和我们下面的例子一样的体例把了局写进到输入流。固然,这个技能并非存储历程独有的,可是和存储过程当中前往的ResultSet分离利用,是一个十分壮大的工具。
结论
存储历程能够匡助你在代码平分离逻辑,这基础上老是无益的。这个分别的优点有:
•疾速创立使用,利用和使用一同改动和改良的数据库形式。
•数据库形式能够在今后改动而不影响Java对象,当我们完成使用后,能够从头计划更好的形式。
•存储历程经由过程更好的SQL嵌进使得庞大的SQL更简单了解。
•编写存储历程比在Java中编写嵌进的SQL具有更好的工具--年夜部分编纂器都供应语法高亮!
•存储历程能够在任何SQL命令行中测试,这使得调试加倍简单。
并非一切的数据库都撑持存储历程,可是存在很多很棒的完成,包含收费/开源的和非收费的,以是移植并非一个成绩。Oracle、PostgreSQL和DB2都有相似的存储历程言语,而且有在线的社区很好地撑持。
存储历程工具良多,有像TOAD或TORA如许的编纂器、调试器和IDE,供应了编写、保护PL/SQL或pl/pgsql的壮大的情况。
存储历程的确增添了你的代码的开支,可是它们和年夜多半的使用服务器比拟,开支小很多。假如你的代码庞大到必要利用DBMS,我倡议全部接纳存储历程的体例。
最后我再次声明,我并没有说不看好java,实际上我对java很乐观的,毕竟她正在不断改进中,我相信她总有一天会和.net并驾齐驱的 你一定会高兴地说,哈哈,原来成为Java高手就这么简单啊!记得Tomjava也曾碰到过一个项目经理,号称Java很简单,只要三个月就可以学会。 你现在最缺的是实际的工作经验,而不是书本上那些凭空想出来的程序。 我大二,Java也只学了一年,觉得还是看thinking in java好,有能力的话看英文原版(中文版翻的不怎么好),还能提高英文文档阅读能力。 是一种语言,用以产生「小应用程序(Applet(s)) J2SE开发桌面应用软件比起 VC,VB,DEPHI这些传统开发语言来说,优势好象并不明显。J2ME对于初学者来说,好象又有点深奥,而且一般开发者很难有开发环境。 关于设计模式的资料,还是向大家推荐banq的网站 http://www.jdon.com/,他把GOF的23种模式以通俗易懂的方式诠释出来,纯Java描述,真是经典中的经典。 一般学编程语言都是从C语开始学的,我也不例外,但还是可能不学过程语言而直接学面向对象语言的,你是刚接触语言,还是从C开始学比较好,基础会很深点,如果你直接学习JAVA也能上手,一般大家在学语言的时候都记一些语言的关键词,常有的包和接口等。再去做逻辑代码的编写,以后的学习过程都是从逻辑代码编写中提升的,所以这方面都是经验积累的。你要开始学习就从 Java是一种计算机编程语言,拥有跨平台、面向对java Pet Store.(宠物店)是SUN公司为了演示其J2EE编程规范而推出的开放源码的程序,应该很具有权威性,想学J2EE和EJB的朋友不要 错过了。 当然你也可以参加一些开源项目,一方面可以提高自己,另一方面也是为中国软件事业做贡献嘛!开发者在互联网上用CVS合作开发,用QQ,MSN,E-mail讨论联系,天南海北的程序员分散在各地却同时开发同一个软件,是不是很有意思呢? 你一定会高兴地说,哈哈,原来成为Java高手就这么简单啊!记得Tomjava也曾碰到过一个项目经理,号称Java很简单,只要三个月就可以学会。 多重继承(以接口取代)等特性,增加了垃圾回收器功能用于回收不再被引用的对象所占据的内存空间,使得程序员不用再为内存管理而担忧。在 Java 1.5 版本中,Java 又引入了泛型编程(Generic Programming)、类型安全的枚举、不定长参数和自动装/拆箱等语言特性。 接着就是EJB了,EJB就是Enterprise JavaBean, 看名字好象它是Javabean,可是它和Javabean还是有区别的。它是一个体系结构,你可以搭建更安全、更稳定的企业应用。它的大量代码已由中间件(也就是我们常听到的 Weblogic,Websphere这些J2EE服务器)完成了,所以我们要做的程序代码量很少,大部分工作都在设计和配置中间件上。 如果你学过HTML,那么事情要好办的多,如果没有,那你快去补一补HTML基础吧。其实JSP中的Java语法也不多,它更象一个脚本语言,有点象ASP。 你就该学一学Servlet了。Servlet就是服务器端小程序,他负责生成发送给客户端的HTML文件。JSP在执行时,也是先转换成Servlet再运行的。虽说JSP理论上可以完全取代Servlet,这也是SUN推出JSP的本意,可是Servlet用来控制流程跳转还是挺方便的,也令程序更清晰。接下来你应该学习一下Javabean了,可能你早就看不管JSP在HTML中嵌Java代码的混乱方式了,这种方式跟ASP又有什么区别呢? 是一种由美国SUN计算机公司(Sun Microsystems, Inc.)所研究而成的语言 是一种为 Internet发展的计算机语言 Java是一种计算机编程语言,拥有跨平台、面向对java J2SE开发桌面应用软件比起 VC,VB,DEPHI这些传统开发语言来说,优势好象并不明显。J2ME对于初学者来说,好象又有点深奥,而且一般开发者很难有开发环境。
页:
[1]
2