仓酷云

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

[学习教程] JAVA网页编程之Java程序员的存储历程

[复制链接]
小魔女 该用户已被删除
跳转到指定楼层
楼主
发表于 2015-1-18 11:42:33 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

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

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

x
JAVA是一种可以撰写跨平台应用软件的面向对象的程序设计语言,由升阳(SunMicrosystems)公司的詹姆斯·高斯林(JamesGosling)等人于1990年代初开发。程序|程序员|存储历程本文论述了怎样利用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)returnsintegerdeclarepoet_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()returnrefcursorasdeclaretoesuprefcursor;beginopentoesupforSELECTpoets.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);getResults.execute();ResultSetrs=(ResultSet)getResults.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);getResults.execute();ResultSetrs=(ResultSet)getResults.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,我倡议全部接纳存储历程的体例。


net程序员的大部门代码都靠控件拖拽完成的,虽然java也有,但是无论从美观和速度上都没发和.net比。java程序员都是代码完成的,所以java程序员常戏称.net程序员是操作员,呵呵。
活着的死人 该用户已被删除
沙发
发表于 2015-1-21 13:01:17 | 只看该作者
[url]http://www.jdon.com/[/url]去下载,或到同济技术论坛的服务器[url]ftp://nro.shtdu.edu.cn[/url]去下,安装上有什么问题,可以到论坛上去提问。
山那边是海 该用户已被删除
板凳
发表于 2015-1-30 18:51:08 | 只看该作者
你可以去承接一些项目做了,一开始可能有些困难,可是你有技术积累,又考虑周全,接下项目来可以迅速作完,相信大家以后都会来找你的,所以Money就哗啦啦的。。。。。。
金色的骷髅 该用户已被删除
地板
发表于 2015-2-5 16:13:37 | 只看该作者
我大二,Java也只学了一年,觉得还是看thinking in java好,有能力的话看英文原版(中文版翻的不怎么好),还能提高英文文档阅读能力。
因胸联盟 该用户已被删除
5#
发表于 2015-2-6 17:31:21 | 只看该作者
Pet Store.(宠物店)是SUN公司为了演示其J2EE编程规范而推出的开放源码的程序,应该很具有权威性,想学J2EE和EJB的朋友不要 错过了。
小妖女 该用户已被删除
6#
发表于 2015-2-17 01:13:40 | 只看该作者
自从Sun推出Java以来,就力图使之无所不包,所以Java发展到现在,按应用来分主要分为三大块:J2SE,J2ME和J2EE,这也就是Sun ONE(Open Net Environment)体系。J2SE就是Java2的标准版,主要用于桌面应用软件的编程;J2ME主要应用于嵌入是系统开发,如手机和PDA的编程;J2EE是Java2的企业版,主要用于分布式的网络程序的开发,如电子商务网站和ERP系统。
若天明 该用户已被删除
7#
发表于 2015-2-20 10:51:13 | 只看该作者
应用在电视机、电话、闹钟、烤面包机等家用电器的控制和通信。由于这些智能化家电的市场需求没有预期的高,Sun公司放弃了该项计划。随着1990年代互联网的发展
乐观 该用户已被删除
8#
发表于 2015-3-6 16:55:57 | 只看该作者
[url]http://www.jdon.com/[/url]去下载,或到同济技术论坛的服务器[url]ftp://nro.shtdu.edu.cn[/url]去下,安装上有什么问题,可以到论坛上去提问。
蒙在股里 该用户已被删除
9#
发表于 2015-3-13 04:20:20 | 只看该作者
自从Sun推出Java以来,就力图使之无所不包,所以Java发展到现在,按应用来分主要分为三大块:J2SE,J2ME和J2EE,这也就是Sun ONE(Open Net Environment)体系。J2SE就是Java2的标准版,主要用于桌面应用软件的编程;J2ME主要应用于嵌入是系统开发,如手机和PDA的编程;J2EE是Java2的企业版,主要用于分布式的网络程序的开发,如电子商务网站和ERP系统。
若相依 该用户已被删除
10#
发表于 2015-3-17 05:10:31 | 只看该作者
J2SE开发桌面应用软件比起 VC,VB,DEPHI这些传统开发语言来说,优势好象并不明显。J2ME对于初学者来说,好象又有点深奥,而且一般开发者很难有开发环境。
冷月葬花魂 该用户已被删除
11#
发表于 2015-3-22 21:05:45 | 只看该作者
还好,SUN提供了Javabean可以把你的JSP中的 Java代码封装起来,便于调用也便于重用。
深爱那片海 该用户已被删除
12#
发表于 2015-4-4 20:58:16 | 只看该作者
Java自面世后就非常流行,发展迅速,对C++语言形成了有力冲击。Java 技术具有卓越的通用性、高效性、平台移植性和安全性,广泛应用于个人PC、数据中心、游戏控制台
小女巫 该用户已被删除
13#
发表于 2015-4-13 02:29:43 | 只看该作者
不过,每次的执行编译后的字节码需要消耗一定的时间,这同时也在一定程度上降低了 Java 程序的运行效率。
飘飘悠悠 该用户已被删除
14#
发表于 2015-5-1 05:10:13 | 只看该作者
你就该学一学Servlet了。Servlet就是服务器端小程序,他负责生成发送给客户端的HTML文件。JSP在执行时,也是先转换成Servlet再运行的。虽说JSP理论上可以完全取代Servlet,这也是SUN推出JSP的本意,可是Servlet用来控制流程跳转还是挺方便的,也令程序更清晰。接下来你应该学习一下Javabean了,可能你早就看不管JSP在HTML中嵌Java代码的混乱方式了,这种方式跟ASP又有什么区别呢?
15#
发表于 2015-5-5 02:36:53 | 只看该作者
Sun公司看见Oak在互联网上应用的前景,于是改造了Oak,于1995年5月以Java的名称正式发布。Java伴随着互联网的迅猛发展而发展,逐渐成为重要的网络编程语言。
海妖 该用户已被删除
16#
发表于 2015-5-6 03:49:55 | 只看该作者
是一种突破用户端机器环境和CPU
兰色精灵 该用户已被删除
17#
发表于 2015-6-8 16:36:35 | 只看该作者
还好,SUN提供了Javabean可以把你的JSP中的 Java代码封装起来,便于调用也便于重用。
谁可相欹 该用户已被删除
18#
发表于 2015-6-14 17:21:38 | 只看该作者
Pet Store.(宠物店)是SUN公司为了演示其J2EE编程规范而推出的开放源码的程序,应该很具有权威性,想学J2EE和EJB的朋友不要 错过了。
透明 该用户已被删除
19#
发表于 2015-6-17 20:20:01 | 只看该作者
你就该学一学Servlet了。Servlet就是服务器端小程序,他负责生成发送给客户端的HTML文件。JSP在执行时,也是先转换成Servlet再运行的。虽说JSP理论上可以完全取代Servlet,这也是SUN推出JSP的本意,可是Servlet用来控制流程跳转还是挺方便的,也令程序更清晰。接下来你应该学习一下Javabean了,可能你早就看不管JSP在HTML中嵌Java代码的混乱方式了,这种方式跟ASP又有什么区别呢?
不帅 该用户已被删除
20#
发表于 2015-7-8 10:34:17 | 只看该作者
还好,SUN提供了Javabean可以把你的JSP中的 Java代码封装起来,便于调用也便于重用。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2024-12-29 08:59

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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