




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第9章访问数据库9.1 jdbc 简介数据库的应用目询已经非常普遍,在应用程序的开发过程中,经常会涉及到访问数 据库。java语言为访问数据库提供了方便的技术。java使用jdbc(java database connectivity)技术进行数据库的访问,如图9所示。 使用jdbc技术进行数据库访问时,java应川程序通过jdbc api和jdbc驱动程序管 理器z间进行通信,例如java应用程序可以通过jdbc api向jdbc驱动程序管理器发 送一个sql査询语句。jdbc驱动程序管理器乂可以以两种方式和最终的数据库进行通 信:一是使用jdbc/odbc桥接驱动程序的间接方式;另一-是使
2、用jdbc驱动程序的直 接方式。图9.1jdbc示意图张动程用管理器ava应用程序jjdbc所采用的这种数据库访问机制使得jdbc驱动程序管理器以及底层的数据库 驱动程序对于开发人员來说是透明的。対于开发人员來说,访问不同类型的数据库时使用的是同一套jdbc apio此外,使用这种机制还有另一个重要的意义:当有新类型的 数据库出现时,只要该数据库的主产厂商提供相应的jdbc驱动程序,已有的java应用 程序不用做任何修改。a/odbc (开放式数据库连接)是一个编程接口,它允许程序访问使用sql(结构化查询语言)作为 数据访间标准的dbms(数据库管理系统)屮的数据。sun公司认为odbc难以
3、掌握、使用复杂并且在 安全性方面存在问题,所以java中没有直接采用odbc模式。在进一步阅读本章z前,请确认您的机器上包含了如下内容: jdbc api正确安装完jdk后,就可以使用jdbc api t ojdbc api有版本1.0和2.0的区别。 jdk1.1中包含的是jdbc api 1.0,并且jdbc api 1.0可以在jdkl1及其后续版本上运 行。jdk1.2中包含的是jdbc api 2.0, jdbc api 2.0可以在jdk1.2及其后续版木上运 行。但是,jdbcapi2.0不能在jdk1.1上运行。 数据库驱动程序数据库驱动程序包括:(djdbc/odbc桥接驱动
4、程序。正确安装完jdk后,即已白动获得了 sun公司提 供的jdbc/odbc桥接驱动程序,并不需要进行任何特殊的配置。(2)odbc驱动程序。如果机器上还没有安装odbc,请根据odbc驱动程序供应 商提供的信息安装并配置odbc驱动程序。(3)访问特定数据库的jdbc驱动程序。例如,如果需要访问ms sql server 2000 上的数据库,那么应该下载并安装ms sqlserver 2000的jdbc驷动程序。参见922 小节。 dbms(数据库管理系统)读者可以根据盂要,选择性地安装dbmso例如,如果盂要和一个运行在ms sql server 2000上的数据库建立连接,那么首先就
5、需要在本机或是其他机器上安装-个 ms sql server 2000 的 dbms。x/odbc和dbms的安装和配冒本身就是技术性很强的工作。如果在安装和配冒过程中存在困 难,最好参考相关的技术文档或是求助这方面的专家。9.2建立数据库连接要想对数据库进行访问,必须先和数据库建立连接。建立一个数据库连接总是需要 两个步骤: 载入驱动程序 建立连接(1)载入驱动程序使用语句:classf orname ("驱动程序名称”);来载入指定名称的驱动程序。例如使用sun公司提供的jdbc/odbc桥接驷动程 序,该驱动程序的名称为“sun.jdbc.odbc.jdbcodbcdriver
6、”,使丿ij卜-面的语句将载入该张 动程序:class forname("sun jdbc.odbc jdbcodbcdriverh);(2)建立连接驱动程序管理器(drivermanager)负责管理驱动程序并使用适当的驱动程序建立和 数据库的连接。可以使用下面的语句建立一个和数据库的连接:connection con = drivermanager .getconnection (url,/ "用户密*马”);url 表示数据库url的一个字符串,其常规语法为jdbc:subprotocol:subname0子协 议subprotocol用于选取连接数据库的特定驱动程序
7、。x/不同的驱动程序,驱动程序名称以及子协议名称是可以不一样的。在随驱动程序提供的文档中 能够找到具体使用方法。正如上-小节所述,jdbc驱动程序管理器可以以两种方式进行数据库访问:-是 使用jdbc/odbc桥接驱动程序;另一种方式是使用jdbc驱动程序直接和数据库连接。 下面将使用两个实例来分别讲解如何使用这两种方式进行数据库访问。9.2.1使用jdbc/odbc桥接驱动程序"准备工作:使用ms access建立一个名为booktest.mdb的数据库,该数据库屮有一张表 bookinfo,该表的的字段名称、数据类型和字段含义见表921。表9.2. 1表book i nfo的字段
8、名及数据类型字段名数据类型描述bookld文本(10)编号(关键字)bookname文本(50)书名bookprice数字(单精度)疋价bookpress文本(50)出版社使用odbc管理工具为booktest.mdb的建立一个名为book的数据源。设定好访问 该数据源的用户名称和密码(本例中分别设定为admin和xyz)。(1) 载入驱动程序使用jdbc/odbc 桥接驱动程序,该驱动程序的名称为 usun.jdbc.odbc.jdbcodbcdriver使丿ij下面的语彳j将载入jdbc/odbc桥接驱动程序: class.forname"sun.j dbc.odbc.jdbco
9、dbcdriver");(2) 建立连接使用下面的语句建立一个和数据库的连接:connection con=drivermanagergetconnection(mjdbc:odbc:bookm,n admin",mxyz");由于本例中使用jdbc/odbc桥,因此子协议使用odbc, subname就是所使用的数 据源名称。例921完整显示了使用jdbc/odbc桥访问access数据库的源代码。该程 序首先载入jdbc/odbc驱动程序,然后和数据源建立连接,最后使用査询语句将 bookinfo表中的所有数据显示到屏幕上(查询语句的使用参见9.3节)。例 9
10、.2.1 jdbcodbc.javaimport java sql.*;public class jdbcodbcpublic static void mainstring args) tryclassforname(hsun jdbc.odbc jdbcodbcdriver");connection con=drivermanagergetconnection(mjdbc:odbc:book",h admin","abch);statement stmt = con.createstatement();resultset rs=stmt.execute
11、query(nselect * from booklnfoh); while(rs.next()system.out printin(rs getstring(1)+h h+rs getstring(2)+h+ rs.getfloat (3)+" ”+rs getstring (4); rsclose(); stmtclose();catch(exception e)e printstacktrace(); 9.2.2使用jdbc驱动程序木小节介绍如何使用jdbc驱动程序直接和运行在ms sqlserver 2000服务器上 的数据库建立连接,x/准备工作:这里使用一个ms sqls
12、erver 2000上的数据库作为例了。先在ms sqlserver 2000上建立一个名为booktest的数据库,并且在该数据库中创建一个名为bookinfo的 表。表bookinfo的字段名、数据类型及字段含义见表922。使用企业管理器为该数据 库创建一个合法的用户,用户名为admin,密码为xyz。下载并安装ms sqlserver 2000的jdbc驱动程序。在安装目录的lib子目录屮, 会发现有三个 jar 文件(msbase.jar、mssqlserver.jar 及 msutil.jar),就是 ms sqlserver 2000的jdbc驱动程序。注意:要使得java应用程序
13、能够访问ms sqlserver 2000 上的数据库,必须使得在类路径中能够找到这三个文件。您可以在环境变量中设置 好classpath;或是更简单一点,直接将这三个.jar文件解压缩到应用程序所在的目 录。表9.2.2表book i nfo的字段名及数据类型字段名数据类型描述bookidvarchar( 10)编号(关键字)booknamcvarchar (50)书名bookpriccfloat定价bookpressvarchar (50)(1) 载入驱动程序ms sqlserver 2000 jdbc驱动程序的名称为(参看该驱动程序安装冃录下的文档) "com.microsof
14、t.jdbc.sqlserve r.sqlservei'dri ver ”。使丿ij下面的语句将载入ms sqlserver 2000 jdbc驱动程序:class fornamehcom.microsoft jdbc sqlserver sqlserverdriverh);(2) 建立连接使用下面的语句建立一个和数据库的连接:string url =mjdbe:microsoft:sqlserver:/127.0.01:1433h;connection con=drivermanagergetconnection(urlz"admin"."xyz&quo
15、t;);con setcatalog("booktesth);本例中使用jdbc驱动程序直接和数据库服务器建立连接,url子协议的书写方式 少上例中有所不同(参看随驱动程序提供的帮助文档)o 是一个特殊的回路地址, 代表本机地址(localhost)o如果ms sql server 2000安装在其他机器上,那么上面的 代码片断中的位置应该填写ms sql server 2000所在机器的ip地址。1433 是数据库服务器的侦听端口号,默认是1433。如杲数据库服务器的侦听端口号定制为其 他的端口号,那么应该修改此处为相应的值。山于一个ms sql
16、 server 2000上可以运 行多个数据库,因此可以使用con.setcatalogo方法指定当前的数据库。 con.setcatalog("booktesth)语句将booktest设定为当前的数据库。例9.2.2完整显示了使川jdbc驱动程序直接访问ms sql server 2000数据库的 源代码,完成和例921相似的功能。例 9.2.2 jdbc.java/使用jdbc直接建立数据库连接import java sql.*; public class jdbc public static void mainstring args)tryclass forname('
17、;com.microsof t jdbc sqlserver .sqlserverdriver");string url =njdbc:microsoft:sqlserver:/127 001:1433";connection con=drivermanager getlconnection (url, “admin". “xyz” ); con setcatalog("booktest”);statement stmt = con.createstatement();resultset rs=stmt.executequery(nselect * fr
18、om booklnfoh); while(rs.next()system.out printin(rs getstring(1)+" h+rs getstring(2)+ h m+rs getfloat (3)+ h m + rs.getstring(4);rsclose ();stmt close();catch (exception e)e printstacktrace();9.2.3使用配置文件读者已经知道,使用jdbc的一个优点就是:数据库编程独立于平台和数据库类型。 也就是数据库类烈改变后,访问数据的代码不需耍改变(数据库驱动程序名称和数据库 url需要做相应的变动)。在
19、例9.1和9.2,驱动程序名称和数据库url都已经被“硬”编 码到应用程序中。一旦所访问的数据库类型改变后,必须修改程序中的驱动程序名称和 数据库url,重新编译后才能运行。这对于应用程序的用户是不能接受的,另一方面也 削减了 jdbc数据库编程独立于数据库类型的优点。町以通过使川配置文件來解决这个 问题:提供一个设置界面,用户可以在该界而中指定驱动程序的名称以及数据库url, 并将结呆保存到一个配置文件中。应用程序进行数据库连接吋使用配置文件中的信息, 这样可以提高应用程序的灵活性。为了简单起见,这里的例子只演示了如何从配置文件中读取信息。在第11章的项 冃实例中演示了如何完整地读写配置文件
20、。在应用程序所在的h录中创建一个配置文件db.cfg,该文件中的内容为:dbdriver=com.microsoft jdbc.sqlserver sqlserverdriverdbip=dbport=1433dbusername=admin dbpassword=xyz de f aultdbname=booktestjava语言中提供了一个类java.util.properties,该类中提供了 load()方法可以从输入 流中读入属性值。下面的语句从配置文件db.cfg中读入配置信息存放到対象prop中: properties prop=new properties()
21、;prop.load(new fileinputstream("db.cfg");从配置文件中读入的配置信息是以(关键字,属性值)对的形式存放在对象prop中的。例如要取得关键字dbdriver的属性值,使用getpropertyo方法:string driver二propgetproperty("dbdriver“);这时候 driver 中的值为"com.microsoft.jdbc.sqlscrvcr.sqlscrverdriver”。例9.2.3演示了如何使用配置文件中的信息来建立数据库连接。例 9.2.3 jdbcprop.javaimport
22、 java sql.*;import java.util properties;import java io *;public class jdbcproppublic static void main(string args)try/读入配置文件properties prop=new properties();prop load new file input st ream (11 db cf g'1);/取得乞个配置信息string driver=prop getproperty("dbdriver");string ip=propgetproperty(&qu
23、ot;dblp");string port=prop getpropertydbport");string username=prop.getproperty(hdbus巳rname”);string password=prop get property (”dbpassword,);string dbname=prop getproperty(ndefaultdbname”);/依据读入的配置信息构建数据库urlstring url =njdbc:microsoft:sqlserver:/" + ip+":n +port;/载入数据库驱动程序class
24、 forname(driver);/建立数据库连接connection con=drivermanagergetconnection(url,usernamezpassword); con.setcatalog(dbname);statement stmt = con cr巳atestatem巳nt();resultset rs=stmt.executequery(nselect * from booklnfo"); while(rs next()system.out printin(rs getstring (1)+ " n + rs getstring(2)+ h &q
25、uot; +rs getfloat (3)+” h + rs.getstring(4);rsclose ();stmt close();catch (exception e)e printstacktrace();a/为了提岛应用程序的安全性,可以对配咒文件中的用户名和用户密码进行加密操作。9.3执行sql语句和数据库建立连接的目的是为了讣应用程序能够和数据库进行交互。首先使用连接 对彖中createstatement()方法创建一个statement対象,然后就可以通过statement対象向 数据库发送各种sql语旬了。statement类型的对象中提供了几种不同的执行sql语句的方法,如
26、: executeupdate(sql)、executequery(sql)、execute(sql) 以及 executebatch()。 executeupdate(sql)方法用来执行那些会修改数据库内容的sql语句, executequery(sql)则用来执行sql杏询语句,execute(sql)方法可以执行任意类型的 sql语句,executebatch()用來批量执行sql语句。9.3.1 executeupdatecxccutcupdatc(sql)方法用来执行那些会修改数据库的sql语句,例如insert, updatedelete 以及 create 等命令。例如,如果要
27、向数据库booktest的bookinfo表中插入一条记录:stmt. executeupdate (h insert into bookinfo values (* b0002 * , 1 程序 设计* ',23.45, 'xx 出版社 j ");9.3.2 executequery如果对数据库进行查询操作,那么使用方法executequery(sql),该方法将返回一 个resultset类型的结果集对象,该対象中包含了所有查询结果。如:resultset rs=stmt.executequery("select * from bookinfo"
28、;);要访问结果集中的一条记录,需要定位到该记录。resultset类型的对彖中提供了 ncxt()方法用于依次定位结果集中的每条记录。x/resultset类型的对象屮有一个游标,指向当前记录。初始时,该游标指向第条记录之前。首 次使用next()方法后,游标指向第一条记录。循环使用next()方法将依次遍历结果集中的每条记录。resultset类型的对彖中还提供了 getxxx()方法,用于访问当前记录中字段的值。 依据字段的sql数据类型的不同,gc(xxx()方法采用不同的形式:如getstring()用于访 问varch如类型的字段,而gelfloat()用于访问float类型的字段
29、。使用getxxx()必须在 方法参数中指明所访问字段的列索引或是列名。例如,要取得当前记录中图书价格:float price=rs .get float (3) ;/歹 u 索引或是:float price=rs.getfloat("bookprice"); /歹u名/与数组下标索引不同,列索引是从1开始的。"注意,如果执行的是如下査询:rcsultsct rs=stmt.cxccutcqucry(hsclcct bookpricc from bookinfo");访问rs中当前记录中的bookprice字段的值,如果使用列索引方式,应该是:float
30、 price=rs.getfloat( 1); 不再是 3也就是说,字段的列索引指的是字段在返冋的记录集中所在列的位置,而不是指字段在数据库表 中所在列的位置。尽管访问每种不同的sql数据类型推荐使用其相应的getxxx()方法,但是在有些 吋候,getxxx()方法也可以访问类型不匹配的sql数据类型,例如:string price=rs.getstring(nbookpricen);上述语旬会将访问到的浮点值转化为字符串。表931显示了 getxxx()方法所能访问的sql数据类型。在该表屮,x表示推荐使 用该x所在行的getxxx()方法访问该x所在列的sql数据类型;x表示可以使用该x
31、 所在行的getxxx()方法访问该x所在列的sql数据类型,但是不推荐使用。9.3.3 cxccutcbatchexecutebatch()方法川來批量执行sql语句。需要注意的是,这些要批量执行的sql 语句是更新类型(如insert> update> delete以及create等)的,即会对数据库进行修改 操作的sql语旬,并且其中不能包含查询类型(select)的sql语句。f面的一段代码演示了如何使用execiitebatch()方法:statement stmt=con createstatement();stmt addbatch(updatesql_l);stmt
32、 addbatch(updatesql_2);stmt addbatch(updatesql_3);int results = smt executebatch();上面的代码片断中,向stmt对象中添加了三条更新类型的sql语句。调用 executebatch()方法后,这三条sql语句将批量执行。该方法返回的是一个整型数组, 其中依次存放了每条sql语句对数据库产生影响的行数。9.3节通过儿个简单的例子讲解了一些基本的jdbc apl尽管演示例子中的sql 语句都非常简单,但是只要驱动程序和dbms支持,完全可以通过这些基本的jdbc api 向dbms发送复杂的sql语句,以满足复杂应用
33、程序的需要。9.4 使用 prepared statement前面的介绍中,使用数据库连接对彖创建statement对彖,然后通过slawment对彖 向dbms发送sql语句。英实还可以通过数据库连接对彖创建prcparcdstatcmcnt类型 的对象,然后通过它向dbms发送sql语句。在冇些情形下,preparedstatement类型的对象与statement类型对象相比,冇如下两 个优点: 效率高 使用方便表9.3.1 getxxx ()方法所能访问的sql数据类型 sql 数据类型 getxxxo 方法:ts m all in tintegerbigintrealf loatd0
34、ubled e cim a lnu mericbitcharva rc harl0ngvarcharb1naryvarbin aryl0n(iv a r b1n a ryd atet11et1mestampgcibytexxxxxxxxxxxxxgetshortxxxxxxxxxxxxxgctlntxxxxxxxxxxxxxgetlongxxxxxxxxxxxxxget floatxxxxxxxxxxxxxgeldoublcxxxxxxxxxxxxxgetbigdecimalxxxxxxxxxxxxxgctboolcanxxxxxxxxxxxxxgetslringxxxxxxxxxxxxxxx
35、xxxxgcibytesxxxget datexxxgcttimexxxxxgcttimcstampxxxxxxgelajiciistreainxxxxxxgetunicodcstreamxxxxxge(binar)rstrcamxxxgetobjecixxxxxxxxxxxxxxxxxxx(i)效率高使用数据库连接对象创建preparedstatement类型的对象时,作为参数的sql语句 会立刻被发送到dbms并进行编译。这样preparedstatement类型的对彖中包含的是预 编译好的sql语句。这样,当需要再次执行preparedstatement类型对象屮的sql语旬 时,dbm
36、s立刻就可以执行其中已经编译好的sql语句。(2)使用方便使用数据库连接对象创建preparedstatement类型的对象时,作为参数的sql语句 屮允许使用参数占位符(?)。这样,在每次运行这条sql语句时,可以通过赋给参数占 位符不同的参数值,从而完成不同的功能。例如:string querysql =hselect * from bookinfo where bookprice > ?h; preparedstatement stmt = con.preparestatement(querysql);上而的两行代码,创建了一个preparedstatement类型的对象stmt,
37、该对象中的sql 语句为"select * from bookinfo where bookprice > ?",这条语句立刻被发送到dbms进 行预编译。还可以发现,上血的这条sql语句中使用了一个参数占位符,因此在执行 stmt对彖中的sql语旬前必须先设定该参数山位符的值。依据参数占位符所指代的数 据类型的不同,选用相应类型的setxxxozt法来设定参数占位符的值。上述代码片断中 山于bookprice是一个浮点数类型的值,因此可以使用setfloat()设定该参数占位符的 值,例如:querysql setfloat(1,10.1);方法setfloat()
38、+第一个参数是参数占位符?的位置索弓i,笫二个参数是赋给该参数 r1位符的值。在设定完参数占位符的值jh ,stmt屮的sql语彳j就是“select * from bookinfo where bookprice >10.1 ”。这时候调用stmt中的executequery()方法就可以返回查询的 结果集:resultset rs= stmt.executequery();"statement类型的对象在执行executequery(sql)方法时,是将sql语句作为executequery(sql) 方法的参数传递进去的。在执行时将sql语句发送给dbms,编译后再执行。
39、而preparedstatement 类型对象的cxccutcqucryo/j'法不需要传递sql语句,它使用的是创建preparedstatement对象时预先 编译好的sql语句。同样,两者的executeupdate()方法也存在类似的区别。如果需要向表bookinfo中插入一条新的记录('b0003tc+;78.50,清华大学出版社), 根据上而所讲的知识,下列的代码片断能够完成该功能:preparedstatement update=con preparestatement(hinsert into bookinfo values(? z ? # ?,?)n);upd
40、ate setstring(1, hb0003 n);update setstring (2 . ,c + +");update setfloat(3, 78 50f);update . setstring (4 ,"清华大学出版社");updateexecuteupdate();上述的代码片断屮,使用了 setxxx()方法逐个设置占位符的值。在实际的应用程序 中,一条记录的字段往往有儿十个,那么使卅这种方式去做的话,程序就会写得很长, 效率不高。这时候,可以使用setobjectott法结合循环语句来设置占位符的值。同样以 上述插入一条记录为例:prepare
41、dstatement update=con.preparestatement(h insert into booklnfovalues(?,?,?z ?)");object line十b0003” jc+sew float (78 50) j清华大学;for(int i=l;i< = line length;i + + )update setobject(i,linei-1);update executeupdate();setobject()方法中冇两个参数:第一个参数是占位符的索引;笫二个参数是对象类 型的值,赋值给占位符所指的参数。需要注意的是,所赋的对象类型必须和占位符
42、所指 参数的sql数据类型相匹配。例如上述代码片断中,将float类型的对象赋值给一个sql 数据类型为了 float的参数,将string类型的对象赋值给sql数据类型为varchar的参数。9.5事务处理先来看一个帐户转移的问题:假设存在两个帐户a和b,现在需要将帐户a上的 部分资金转移到帐户b中。使用下面的代码:preparedstatement stmt_l = con.preparedstatement(sqll);preparedstatement stmt_2 = con.preparedstatement(sql2);stmt_l. executeupdate () ; / s
43、tmt_l语句的作用是:从帐户a减去资金x stmt_2 . executeupdate () ; / stmt_2语句的作用是:将帐户b加上资金x 如果一切正常,上面的代码片断完成资金转移的功能。然而,实际情况可能不是这 么简单。例如,如果语句stmt_l止常执行完毕,而语句stmt_2在执行时出现异常,那 么就会出现数据的不一致性:帐八a上的资金减少了 x,而帐户b上资金并没有增加。 这种情况显然是不能接受的。要解决这个问题,我们希望:语旬stmt.l和语句stmt_2组成一个执行单元,并且 只冇在stmt.l和stmt_2均正确执行完毕后,才对数据库产生影响;任何一个语旬出错 都退回到这
44、个执行单元执行z前的状态。这个执行单元就被称z为事务。在缺省状态下,仓i建的连接是处于自动递交(auto commit)模式:每条语句执行完毕 后,立即向dbms递交执行结果。亦即每条语句独立构成一个事务。因此为了让若干 条语句构成一个事务,在执行第一条语句前先关闭自动递交模式,使用如下方法:con.setautocommit(false);在将口动递交模式设置为false后,所执行的语句不会将执行结果递交给dbms, 直到调用如下的递交语句:con commit();因此,要在上述的帐户转移定制事务,使用下而的代码片断: con. setautocommit (false) ;/ 设为非门动
45、递交模式preparedstatement stmt_lpreparedstatement stmt_2= conpreparedstatement(sql1);= con.preparedstatement(sql2);stmt_l. executeupdate () ; /执行完毕后不立刻递交stmt_2executeupdate () ; /执行完毕js不立刻递交con. commit () ;/ 递交事务con. setautocommit (true) ; / 恢复自动递交模式stmt 1.close ();stmt_2close();上述代码中,stmt_l和stmt_2组成了一个
46、事务。stmt_l和stmt_2执行完毕后,并 不立即递交,直到执行完mito语句后,这两条语句作为一个整体同时递交。 con.setautocommit(true)®句再将连接恢复为原先的自动递交模式。再回到上述的问题:语句sunt_l正常执行完毕,而语句stmt_2在执行时出现杲常。 这吋候,就需要放弃该事务,并且恢复到事务开始吋的状态。为此,可以把事务放在一 个try块中,在对应的catch块中捕获事务执行过程小所出现的异常。一口有异常出现, 可以调用rollback()方法进行事务回滚,恢复到事务开始时的状态。这样就可以侑效地 保持数据库数据的完整性和一致性。如:trycon
47、.setautocommit(false);preparedstatement stmt_l = preparedstatement stmt_2 = stmt_lexecuteupdate(); / stmt_2 executeupdate(); / con. commit () ; / 递交事务/设宜为非自动递交模式con.preparedstatement(sql1); con.preparedstatement(sql2); 执行完毕后不立刻递交执行完毕后不立刻递交con. setautocommit (true) ; / 恢复 h动递交模式 stmt_l close();stmt_2
48、 close ();catch(sqlexception e)e.printstacktrace();if (con != null)trycon rollback () ;/事务回滚con. setautocommit (true) ; / 恢复自动递交模式 catch(sqlexception ex) ex.printstacktrace();由于事务回滚仍可能抛出界常,因此同样需要使用try-catch块來捕获界常。此外, 由于在事务执行的过程中一旦抛出界常,将不会执行con.setautocomniit(true)语句,所 以需要在执彳亍事务回滚语句con.rollbackojm
49、9;,再调用con.setautocommit(true)i5yiij将连 接恢复为原先的自动递交模式。9.6编写数据库工具类java编程语言屮提供了用于数据库访问的各种apl有的时候,一些api总是要纟r 合在一起使用。例如,要建立一个数据录连接,总是需要先载入数据库驱动程序,然后 使用驱动程序管理器建立连接。为此,我们可以编写一个方法(如例961屮的 acquireconnection(),该方法完成载入数据库驱动程序并使用驱动程序管理器建立连接), 然后将该方法封装到一个自定义的类屮(如例9.6.1屮的sqlutil类)。这样,耍创建一个 数据库连接,只需要一个语彳山connection
50、 con=sqluti1.acquireconnection(.);这样可以更加高效、简洁地编写出应用程序。在例961中,类sqlutil被打包到edu.njust.cso因此在其他的类中需要使用类sqlutil 的时候,必须先使用:import edu njust cs ;或是:import edu njust cs sqlutil;來引入(import)sqlutil 类。sqlutil类屮集成了读写数据库和表格的一些方法,包括将数据库屮的记录读入表格 以及将表格屮的数据写入数据库等等。木节屮sqlutil类屮的方法还相当少,读者可以 逐步向其中添加更多的实用方法来丰富该类的内容。在第11
51、章中,读者将会看到sqlutil 类中会拥有更多的实用方法。我们希望数据库中存储的了段值不岀现空值(null),这样可以在应用程序中减少很多 烦人的空值条件判断。为此,当字段值为空值时,町以考虑使川特殊值來代替。例如, 一个double类型的字段,可以用double.negativejnfinite这个特殊值来代替空值。 也就是说,在数据库中,如果一个数据字段的值为double.negativejnfinite,表示 该字段值为空值。便用这种处理方式后,当需耍将字段值为空值(已经由特殊值表示)的 字段读入到表格屮显示时,需要将表示空值的特殊值转化为真正的空值(null),这样才能 使得表格正确
52、显示。sqlutil类屮捉供了一个方法getlinefortablefromlinefordb(),该 方法将适合数据库存储的一行数据(空值由特殊值表示)转化为适合表格显示的数据:依 次判断字段值,如果是一个表示空值的特殊值,则将其转换为空值(null)。由于不同的数 据类型,所定义的代表空值的特殊值是不同的(例如,整型可以是integer.min_value), 因此,需要依据每个字段的数据类型來判断是否使用了特殊值代替空值。出于演示目的, 本节屮的所给岀的方法getlinefortablefromlinefordb()目前还很不完善,只考虑了 3 种数据类型 strings double
53、和 integer。例 9.6.1 sqlutil.javapackage edu.njust cs;import java sql *;import javax swing *;import javautil*;import java io;public class sqlutil/读入配置文件public static properties loadproperty(string filename)properties prop=new properties ();tryfileinputstream in=new fileinputstream(system.getproperties(
54、)get(nuser.dif”)+h/n+filename);prop load(in);in.close ();catch(ioexception e)e.printstacktrace();joptionpane showmessagedialog(null,“配登文件丢失!n建议垂新安装程序“,“信息”,joptionpane.error_message);prop=null;return prop;/建立和ms sql server的连接public static connection acquireconnection(string host,string portz string dbname,string user,string pwd) throws classnotfoundexception,sqlexception connection connection=null; tryclass forname("com.microsoft jdbc sqlserver sqlserverdriver"); string url =11 jdbc :
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 城市轨道交通设计内容
- 威伯科WABCO ABS系统培训报告
- 学前课程内容学时安排
- 幼儿园科学教育活动及设计方案
- 演讲比赛活动设计
- 幼儿园大班安全教案:高温防中暑全攻略
- 2025汽车买卖合同版范本
- 2025个人借款合同范本参考
- 小班国庆假期安全
- 2025钢筋供应合同(版)
- 2024年中国光大银行招聘考试真题
- 2025-2030中国油漆和涂料消光剂行业市场发展趋势与前景展望战略研究报告
- 2025年山西焦煤集团国际发展股份有限公司招聘笔试参考题库附带答案详解
- 水泥装卸合同协议
- 金华兰溪市卫健系统普通高校招聘医学类笔试真题2024
- 2025年浙江省杭州市萧山区中考一模数学模拟试卷(含详解)
- 道路普通货运企业安全生产达标考评方法和考评实施细则
- DB15T 3516-2024野生动物救护站建设规范
- 火灾自动报警系统设计规范完整版2025年
- 能源消防安全课件
- 演唱会可行性研究报告
评论
0/150
提交评论