WEB應(yīng)用及開發(fā)-10JDBC及數(shù)據(jù)庫(kù)(JDBC及SQL語(yǔ)句、存儲(chǔ)過(guò)程應(yīng)用)_第1頁(yè)
WEB應(yīng)用及開發(fā)-10JDBC及數(shù)據(jù)庫(kù)(JDBC及SQL語(yǔ)句、存儲(chǔ)過(guò)程應(yīng)用)_第2頁(yè)
WEB應(yīng)用及開發(fā)-10JDBC及數(shù)據(jù)庫(kù)(JDBC及SQL語(yǔ)句、存儲(chǔ)過(guò)程應(yīng)用)_第3頁(yè)
WEB應(yīng)用及開發(fā)-10JDBC及數(shù)據(jù)庫(kù)(JDBC及SQL語(yǔ)句、存儲(chǔ)過(guò)程應(yīng)用)_第4頁(yè)
WEB應(yīng)用及開發(fā)-10JDBC及數(shù)據(jù)庫(kù)(JDBC及SQL語(yǔ)句、存儲(chǔ)過(guò)程應(yīng)用)_第5頁(yè)
已閱讀5頁(yè),還剩62頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第十講課題JDBC與數(shù)據(jù)庫(kù)(JDBC與SQL語(yǔ)句、存儲(chǔ)過(guò)程的應(yīng)用)目的要求掌握J(rèn)DBC存取各種不同數(shù)據(jù)庫(kù)的方法教學(xué)重點(diǎn)掌握J(rèn)DBC與不同數(shù)據(jù)庫(kù)的連接字符串、連接池教學(xué)難點(diǎn)JSP如何存取存儲(chǔ)過(guò)程中輸入?yún)?shù)、輸出參數(shù)、輸入輸出參數(shù)教學(xué)課時(shí)4(含2課時(shí)上機(jī))教學(xué)方法講解、示例與啟發(fā)式教學(xué)相結(jié)合教學(xué)內(nèi)容和步驟10.1JDBC與數(shù)據(jù)庫(kù)編程10.1.1JDBC的Driver可分為以下四種類型

(1)JDBC-ODBCBridge和ODBCDriver這種驅(qū)動(dòng)器器通過(guò)ODBC驅(qū)動(dòng)器提供數(shù)據(jù)庫(kù)連接。使用這種驅(qū)動(dòng)器,要求每一臺(tái)客戶機(jī)都裝入ODBC的驅(qū)動(dòng)器。

(2)Native-APIpartly-JavaDriver這種驅(qū)動(dòng)器將JDBC指令轉(zhuǎn)化成所連接使用的DBMS的操作形式。各客戶機(jī)使用的數(shù)據(jù)庫(kù)可能是Oracle,可能是Sybase,也可能是Access,都需要在客戶機(jī)上裝有相應(yīng)DBMS的驅(qū)動(dòng)程序。

(3)JDBC-NetAll-JavaDriver這種驅(qū)動(dòng)器將JDBC指令轉(zhuǎn)化成獨(dú)立于DBMS的網(wǎng)絡(luò)協(xié)議形式,再由服務(wù)器轉(zhuǎn)化為特定DBMS的協(xié)議形式。有關(guān)DBMS的協(xié)議由各數(shù)據(jù)庫(kù)廠商決定。這種驅(qū)動(dòng)器可以聯(lián)接到不同的數(shù)據(jù)庫(kù)上,最為靈活。目前一些廠商已經(jīng)開始添加JDBC的這種驅(qū)動(dòng)器到他們已有的數(shù)據(jù)庫(kù)中介產(chǎn)品中。要注意的是,為了支持廣域網(wǎng)存取,需要增加有關(guān)安全性的措施,如防火墻等等。

(4)Native-protocolAll-JavaDriver這種驅(qū)動(dòng)器將JDBC指令轉(zhuǎn)化成網(wǎng)絡(luò)協(xié)議后不再轉(zhuǎn)換,由DBMS直接使用。相當(dāng)于客戶機(jī)直接與服務(wù)器聯(lián)系,對(duì)局域網(wǎng)適用。在這四種驅(qū)動(dòng)器中,后兩類“純Java”(All-Java)的驅(qū)動(dòng)器效率更高,也更具有通用性。但目前第一、第二類驅(qū)動(dòng)器比較容易獲得,使用也較普遍。10.1.2關(guān)于JDBCUrl語(yǔ)法如下:

jdbc:<子協(xié)議>:<子名稱><子協(xié)議>驅(qū)動(dòng)程序名稱或數(shù)據(jù)庫(kù)連接機(jī)制,子協(xié)議名稱的典型例子就是ODBC,如:jdbc:odbc:fff<子名稱>一種標(biāo)識(shí)數(shù)據(jù)庫(kù)的方法。子名稱可以依據(jù)不同的子協(xié)議而發(fā)生變化如:jdbc:dbnet//womat:356//fffODBC子協(xié)議:Jdbc:odbc:<數(shù)據(jù)源名稱>[;<屬性名>=<屬性值>]如:

jdbc:odbc:sqlconn:UID=sa;PWD=ww10.2JDBC編程10.2.1程序基本結(jié)構(gòu)一般的JDBC程序都完成三項(xiàng)功能:與數(shù)據(jù)庫(kù)建立連接;傳送SQL聲明以及對(duì)返回結(jié)果進(jìn)行處理。下面我們通過(guò)一個(gè)具體例子說(shuō)明這三項(xiàng)功能的實(shí)現(xiàn)過(guò)程。例1:Creage.java給出了一個(gè)簡(jiǎn)單的JDBC程序,此程序執(zhí)行后創(chuàng)建一張名為testTable的表,表中包括兩個(gè)域,域名分別為id和name。import.URL;importjava.sql.*;classCreate{publicstaticvoidmain(String[]args){Stringurl="jdbc:odbc:demo";Stringquery="CREATETABLEtestTable"+"(idINT,nameCHAR(10))";try{//下載jdbc-odbcbridge驅(qū)動(dòng)器

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");//關(guān)于此句參見下面Cyclone的注釋//與驅(qū)動(dòng)器建立連接,這里可使用不同的特定驅(qū)動(dòng),如jdbcfororacle或jdbcforsqlserverConnectioncon=DriverManager.getConnection(url,"user","password");//創(chuàng)建一個(gè)Statement對(duì)象Statementstmt=con.createStatement();//執(zhí)行SQL聲明stmt.executeUpdate(query);System.out.println("Createsuccessfully!");//關(guān)閉stmstmt.close();//關(guān)閉連接con.close();}catch(SQLExceptionex){//SQL異常信息System.out.println("\n***SQLExceptioncaught***\n");while(ex!=null){System.out.println("SQLState:"+ex.getSQLState());System.out.println("Message:"+ex.getMessage());System.out.println("Vendor:"+ex.getErrorCode());ex=ex.getNextException();System.out.println("");}}catch(java.lang.Exceptionex){ex.printStackTrace();}}}2.2Statement類及其子類1)Statement接口Statementstmt=con.createStatement();//執(zhí)行SQL聲明intcount1=stmt.executeUpdate("INSERTINTOtestTable(id,name)VALUES(1,'wu')");intcount2=stmt.executeUpdate("INSERTINTOtestTable(id,name)VALUES(2,'wang')");2)PreparedStatement接口Stringdata[][]={{"5","xu"},{"6","yan"}};PreparedStatement

pstmt=con.prepareStatement("INSERTINTOtestTable(id,name)VALUES(?,?)");//參數(shù)賦值,執(zhí)行SQL聲明for(inti=0;i<data.length;i++){pstmt.setInt(1,Integer.parseInt(data[i][0]));pstmt.setString(2,data[i][1]);

pstmt.executeUpdate();}3)CallableStatement接口

CallableStatement

cstmt=con.prepareCall("{callSearch(?)}");//參數(shù)賦值cstmt.setInt(1,934678);//執(zhí)行儲(chǔ)存過(guò)程。cstmt.execute();2.3結(jié)果集ResultSet及ResultSetMetaDataStringquery="SELECT*FROMtestTable";Statementstmt=con.createStatement();//發(fā)出查詢要求,獲得結(jié)果集ResultSet

rs=stmt.executeQuery(query);//顯示結(jié)果集各行各列System.out.println("ThedetailoftestTableis:");ResultSetMetaData

rsmd=rs.getMetaData();//獲得結(jié)果集列數(shù)innumCols=rsmd.getColumnCount();//顯示列標(biāo)題for(inti=1;i<=numCols;i++){if(i>1)System.out.print(",");System.out.print(rsmd.getColumnLabel(i));}System.out.println("");//顯示結(jié)果集信息while(rs.next()){//顯示一行for(inti=1;i<=numCols;i++)

{if(i>1)System.out.print(",");System.out.print(rs.getString(i));}2.4DatabaseMetaDataDatabaseMetaData

dma=con.getMetaData();//驅(qū)動(dòng)器和URL信息System.out.println("\nConnectedto"+dma.getURL());System.out.println("Driver"+dma.getDriverName());System.out.println("Version"+dma.getDriverVersion()//數(shù)據(jù)庫(kù)信息System.out.println("\nDataBasename:"+dma.getDatabaseProductName()+dma.getDatabaseProductVersion());System.out.println("DataBasesupportsSQLkeywords:\n\t"+dma.getSQLKeywords());//數(shù)據(jù)庫(kù)功能信息函數(shù)dma.supportsANSI92EntryLevelSQL()dma.supportsANSI92FullSQL()dma.supportsStoredProcedures()10.2.2JDBC數(shù)據(jù)類型及類型轉(zhuǎn)換⑴JDBC的數(shù)據(jù)類型

JDBC的sql包中除了與數(shù)據(jù)庫(kù)連接有關(guān)的抽象接口及與驅(qū)動(dòng)器有關(guān)的DriverManager、DriverPropertyInfo等類型外,還定義了若干數(shù)據(jù)類,用以代表數(shù)據(jù)庫(kù)中可能用到的SQL類型。下面我們就對(duì)它們逐一進(jìn)行簡(jiǎn)略介紹。①sql.Date

sql包中的日期類Date是util包中Date類的子類,實(shí)際上也是util.Date類的子集。它只處理年月日,而忽略小時(shí)和分秒,用以代表SQL的DATE信息。

Date類的構(gòu)造方法為:

publicDate(intyear,intmouth,intday)其中參數(shù)格式同util.Date類的構(gòu)造方法一樣,年參數(shù)為所需設(shè)定的年份減去1900所得的整數(shù)值,月參數(shù)為0至11,日參數(shù)為1至31。如1998年1月23日所對(duì)應(yīng)創(chuàng)建日期類的方法調(diào)用為:

Dated=newDate(98,0,23);

Date類還提供兩個(gè)與String類互相轉(zhuǎn)換的方法,分別是:

publicstaticDatevalueOf(Strings)將字符串類參數(shù)轉(zhuǎn)換為日期類對(duì)象。其中String類參數(shù)S的格式為“年-月-日”,加“1997-04-12”。

publicStringtoString()將日期類對(duì)象轉(zhuǎn)換為String類對(duì)象表示,同樣采用“年-月-日”的格式。②sql.Time該類是util.Date類的子類,也是它的一個(gè)子集。在Time類里,只處理小時(shí)和分秒,代表SQL的TIME類型。它與sql.Date合起來(lái)才表示完整的util.Date類信息。

Time類的構(gòu)造方法為:

publicTime(int

hour,int

minute,intsecond)其中小時(shí)參數(shù)值為0至23,分秒?yún)?shù)取值均為0至59。與sql.Date一樣,Time類也定義了兩個(gè)與String類互相轉(zhuǎn)換的函數(shù)ValueOf和String。不同的是String類對(duì)象的格式為“小時(shí):分:秒”,如“12:26:06”。③sql.Timestamp這個(gè)類也是util.Date類的子類,其中除了包含年月日、小時(shí)和分秒和信息之外,還加入了納秒信息(nanosecond),1納秒即1毫微秒。Timestamp類用來(lái)代表SQL時(shí)間戳(Timestamp)類型信息。

Timestamp類的構(gòu)造方法為:

publicTimestamp(intyear,intmouth,intdate,inthour,intminute,intsecond,int

nano)其中納秒?yún)?shù)的取值從0至999,999,999,其余各參數(shù)同前。

Timestamp類特別定義了設(shè)置和獲得納秒信息的方法,分別是

publicgetnanos()獲取時(shí)間戳的納秒部分

publicvoidsetNanos(intn)以給定數(shù)值設(shè)置時(shí)間戳的納秒部分④sql.Types

Types類是Object類的直接子類。在這個(gè)類中以靜態(tài)常量的形式定義了可使用的SQL的數(shù)值類型。所有這些類型常量都以前綴

publicfinalstaticint的形式標(biāo)明是公有靜態(tài)整數(shù),且不可改動(dòng)。具體的類型名和含義如表11.1所示。其中OTHER用來(lái)代表數(shù)據(jù)庫(kù)定義的特殊數(shù)據(jù),可以用getObject或setObject方法將其映射為一個(gè)Java的Object對(duì)象。表1Types中定義的SQL類型類型名含義BIGINT長(zhǎng)整型數(shù)BINARY二進(jìn)制數(shù)BIT比特?cái)?shù)CHAR字符型DATE日期型DECIMAL十進(jìn)制數(shù)DOUBLE雙精度數(shù)FLOAT浮點(diǎn)數(shù)INTEGER整數(shù)LONGVARBINARY可變長(zhǎng)型二進(jìn)制數(shù)LONGVARCHAR可變長(zhǎng)型字符NULL空類型NUMERIC數(shù)值型OTHER其他類型REAL實(shí)數(shù)SMALLINT短整型TIME時(shí)間類型TIMESTAMP時(shí)間戳類型TINYINT微整型VARBINARY可變二進(jìn)制數(shù)VARCHAR可變字符型⑵SQL與Java由于SQL數(shù)據(jù)類型與Java的數(shù)據(jù)類型不一致,因而在使用Java類型的應(yīng)用程序與使用SQL類型的數(shù)據(jù)庫(kù)之間,需要某種讀寫類型轉(zhuǎn)換機(jī)制。實(shí)際上我們前面介紹的ResultSet類的“get”系列方法,Statement及其子類的“set“系列方法和registerOutParameter方法,都是這一轉(zhuǎn)換機(jī)制的組成部分。需要進(jìn)行的讀寫轉(zhuǎn)換包括下面情況:從數(shù)據(jù)庫(kù)中讀取數(shù)值后,存放在ResultSet對(duì)象中的是SQL類型的數(shù)據(jù)。而調(diào)用“get”系列方法時(shí),JDBC才將SQL類型轉(zhuǎn)換為指定的Java類型。在一般情形下,SQL類型相對(duì)應(yīng)的Java類型如表11-2所示。⑵SQL與Java由于SQL數(shù)據(jù)類型與Java的數(shù)據(jù)類型不一致,因而在使用Java類型的應(yīng)用程序與使用SQL類型的數(shù)據(jù)庫(kù)之間,需要某種讀寫類型轉(zhuǎn)換機(jī)制。實(shí)際上我們前面介紹的ResultSet類的“get”系列方法,Statement及其子類的“set“系列方法和registerOutParameter方法,都是這一轉(zhuǎn)換機(jī)制的組成部分。需要進(jìn)行的讀寫轉(zhuǎn)換包括下面情況:從數(shù)據(jù)庫(kù)中讀取數(shù)值后,存放在ResultSet對(duì)象中的是SQL類型的數(shù)據(jù)。而調(diào)用“get”系列方法時(shí),JDBC才將SQL類型轉(zhuǎn)換為指定的Java類型。在一般情形下,SQL類型相對(duì)應(yīng)的Java類型如表11-2所示。表2SQL類型一般所對(duì)應(yīng)的Java類型SQLtypeJavatypeCHARjava.lang.StringVARCHARjava.lang.StringLONGVARCHARjava.lang.StringNUMERICjava.lang.BignumDECIMALjava.lang.Bignum⑶字符類型JDBC字符串?dāng)?shù)據(jù)類型為CHAR、VARCHAR和LONGVARCHAR。類型說(shuō)明Fixed-lengthSQLServerchar

和nchar

數(shù)據(jù)類型直接映射到JDBCCHAR

類型。這些都是在列具有SETANSI_PADDINGON的情況下,具有由服務(wù)器提供的填充的固定長(zhǎng)度的類型。對(duì)于nchar,填充始終是打開的,但對(duì)于char,在未填充服務(wù)器字符列的情況下,JDBC驅(qū)動(dòng)程序?qū)⑻砑犹畛?。Variable-lengthSQLServervarchar

和nvarchar

類型直接映射到JDBCVARCHAR類型。LongSQLServertext和ntext

類型映射到JDBCLONGVARCHAR類型。對(duì)于SQLServer2005來(lái)說(shuō),這些類型已過(guò)時(shí),因此應(yīng)改用大值類型。針對(duì)text和ntext

服務(wù)器列使用update<NumericType>和updateObject(int,java.lang.Object)

方法時(shí)將失敗。然而,對(duì)于text和ntext

服務(wù)器列,支持將setObject

方法用于指定的字符轉(zhuǎn)換類型。⑷二進(jìn)制字符串類型JDBC二進(jìn)制字符串類型為BINARY、VARBINARY和LONGVARBINARY。類型說(shuō)明固定長(zhǎng)度SQLServerbinary類型直接映射到JDBCBINARY類型。這是在列具有SETANSI_PADDINGON的情況下,具有由服務(wù)器提供填充的固定長(zhǎng)度類型。沒有填充服務(wù)器char列時(shí),JDBC驅(qū)動(dòng)程序會(huì)添加填充。SQLServertimestamp類型是具有8個(gè)字節(jié)的固定長(zhǎng)度的JDBCBINARY類型??勺冮L(zhǎng)度SQLServervarbinary

類型映射到JDBCVARBINARY類型。LongSQLServerimage類型映射到JDBCLONGVARBINARY類型。對(duì)于SQLServer2005來(lái)說(shuō),該類型已過(guò)時(shí),因此應(yīng)改用大值類型。SQLServer2005中的udt

類型作為L(zhǎng)ONGBINARY類型映射到JDBC。⑸精確數(shù)字類型JDBC精確數(shù)字類型直接映射到其對(duì)應(yīng)的SQLServer

類型。類型說(shuō)明BITJDBCBIT類型表示可能是0或1的單個(gè)位。此類型映射到SQLServerbit類型。TINYINTJDBCTINYINT類型表示單個(gè)字節(jié)。此類型映射到SQLServertinyint

類型。SMALLINTJDBCSMALLINT類型表示有符號(hào)的16位整數(shù)。此類型映射到SQLServersmallint

類型。INTEGERJDBCINTEGER類型表示有符號(hào)的32位整數(shù)。此類型映射到SQLServerint

類型。BIGINTJDBCBIGINT類型表示有符號(hào)的64位整數(shù)。此類型映射到SQLServerbigint

類型。NUMERICJDBCNUMERIC類型表示固定精度的十進(jìn)制值,它可存放相同精度的值。NUMERIC類型映射到SQLServernumeric類型。DECIMALJDBCDECIMAL類型表示固定精度的十進(jìn)制值,它可存放至少具有指定精度的值。DECIMAL類型映射到SQLServerdecimal類型。JDBCDECIMAL類型還映射到SQLServermoney和smallmoney

類型,這些類型是特定的固定精度的十進(jìn)制類型,分別以8個(gè)字節(jié)和4個(gè)字節(jié)進(jìn)行存儲(chǔ)。⑹近似數(shù)字類型JDBC近似數(shù)值數(shù)據(jù)類型為REAL、DOUBLE

和FLOAT。類型說(shuō)明

REALJDBCREAL

類型具有7位精度(單精度)并直接映射到SQLServerreal

類型。DOUBLEJDBCDOUBLE類型具有15位精度(雙精度)并直接映射到SQLServerfloat類型。JDBCFLOAT類型是DOUBLE的同義詞。由于FLOAT與DOUBLE之間可能存在沖突,因此DOUBLE為首選類型。⑺日期時(shí)間類型JDBCTIMESTAMP類型映射到SQLServerdatetime

和smalldatetime

類型。datetime

類型以兩個(gè)4字節(jié)整數(shù)進(jìn)行存儲(chǔ)。smalldatetime

類型可存放相同的信息(日期和時(shí)間),但精度較低,為兩個(gè)2字節(jié)的小整數(shù)。10.3JDBC與數(shù)據(jù)庫(kù)的連接字符串⑴MySQL()mm.mysql-2.0.2-bin.jarClass.forName("org.gjt.mm.mysql.Driver");cn=DriverManager.getConnection("jdbc:mysql://MyDbComputerNameOrIP:3306/myDatabaseName",sUsr,sPwd);⑵Oracle(/ip/deploy/database/oracle9i/)classes12.zipClass.forName("oracle.jdbc.driver.OracleDriver");cn=DriverManager.getConnection("jdbc:oracle:thin:@MyDbComputerNameOrIP:1521:ORCL",sUsr,sPwd);⑶Sybase()jconn2.jarClass.forName("com.sybase..jdbc.SybDriver");cn=DriverManager.getConnection("jdbc:sybase:Tds:MyDbComputerNameOrIP:2638",sUsr,sPwd);//(Default-Username/Password:"dba"/"sql")⑷MicrosoftSQLServer(http://)Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");cn=DriverManager.getConnection("jdbc:microsoft:sqlserver://MyDbComputerNameOrIP:1433;databaseName=master",sUsr,sPwd);⑸ODBCClass.forName("sun.jdbc.odbc.JdbcOdbcDriver");Connectioncn=DriverManager.getConnection("jdbc:odbc:"+sDsn,sUsr,sPwd);⑹informix

Class.forName("rmix.jdbc.IfxDriver").newInstance();Stringurl="jdbc:informix-sqli://9:1533/testDB:INFORMIXSERVER=myserver;user=testuser;password=testpassword";⑺sybaseClass.forName("com.sybase.jdbc.SybDriver")url="jdbc:sybase:Tds::2638/asademo";SybConnectionconnection=(SybConnection)DriverManager.getConnection(url,"dba","sql");

例2:queryBook.jsp<%@pagecontentType="text/html;charset=gb2312"%><%@pagelanguage="java"import="java.sql.*,java.io.*"%><HTML><BODY><CENTER><FONTSIZE=5COLOR=blue>圖書信息瀏覽</FONT><tableborder=3><tr><td><b><center>ID號(hào)</td><td><b><center>書名</td><td><b><center>出版社</td><td><b><center>價(jià)格</td></tr><%Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance();Connectioncon=java.sql.DriverManager.getConnection("jdbc:microsoft:sqlserver://:1433;DatabaseName=jspdb","sa","");Statementstmt=con.createStatement();ResultSet

rst=stmt.executeQuery("select*frombook;");while(rst.next()){out.println("<tr>");out.println("<td>"+rst.getString("bkld")+"</td>");out.println("<td>"+rst.getString("bkName")+"</td>");out.println("<td>"+rst.getString("bkPublisher")+"</td>");out.println("<td>"+rst.getFloat("bkPrice")+"元"+"</td>");out.println("</tr>");}rst.close();stmt.close();con.close();%></table></BODY></HTML>10.4連接池⑴連接池原理

連接池技術(shù)的核心思想是:連接復(fù)用,通過(guò)建立一個(gè)數(shù)據(jù)庫(kù)連接池以及一套連接使用、分配、管理策略,使得該連接池中的連接可以得到高效、安全的復(fù)用,避免了數(shù)據(jù)庫(kù)連接頻繁建立、關(guān)閉的開銷。另外,由于對(duì)JDBC中的原始連接進(jìn)行了封裝,從而方便了數(shù)據(jù)庫(kù)應(yīng)用對(duì)于連接的使用(特別是對(duì)于事務(wù)處理),提高了開發(fā)效率,也正是因?yàn)檫@個(gè)封裝層的存在,隔離了應(yīng)用的本身的處理邏輯和具體數(shù)據(jù)庫(kù)訪問邏輯,使應(yīng)用本身的復(fù)用成為可能。連接池主要由三部分組成:連接池的建立、連接池中連接的使用管理、連接池的關(guān)閉。⑵連接池的管理連接池管理策略是連接池機(jī)制的核心。當(dāng)連接池建立后,如何對(duì)連接池中的連接進(jìn)行管理,解決好連接池內(nèi)連接的分配和釋放,對(duì)系統(tǒng)的性能有很大的影響。連接的合理分配、釋放可提高連接的復(fù)用,降低了系統(tǒng)建立新連接的開銷,同時(shí)也加速了用戶的訪問速度。下面介紹連接池中連接的分配、釋放策略。

連接池的分配、釋放策略對(duì)于有效復(fù)用連接非常重要,我們采用的方法是一個(gè)很有名的設(shè)計(jì)模式:ReferenceCounting(引用記數(shù))。該模式在復(fù)用資源方面應(yīng)用的非常廣泛,把該方法運(yùn)用到對(duì)于連接的分配釋放上,為每一個(gè)數(shù)據(jù)庫(kù)連接,保留一個(gè)引用記數(shù),用來(lái)記錄該連接的使用者的個(gè)數(shù)。具體的實(shí)現(xiàn)方法是:當(dāng)客戶請(qǐng)求數(shù)據(jù)庫(kù)連接時(shí),首先查看連接池中是否有空閑連接(指當(dāng)前沒有分配出去的連接)。如果存在空閑連接,則把連接分配給客戶并作相應(yīng)處理(即標(biāo)記該連接為正在使用,引用計(jì)數(shù)加1)。如果沒有空閑連接,則查看當(dāng)前所開的連接數(shù)是不是已經(jīng)達(dá)到maxConn(最大連接數(shù)),如果沒達(dá)到就重新創(chuàng)建一個(gè)連接給請(qǐng)求的客戶;如果達(dá)到就按設(shè)定的maxWaitTime(最大等待時(shí)間)進(jìn)行等待,如果等待maxWaitTime后仍沒有空閑連接,就拋出無(wú)空閑連接的異常給用戶。當(dāng)客戶釋放數(shù)據(jù)庫(kù)連接時(shí),先判斷該連接的引用次數(shù)是否超過(guò)了規(guī)定值,如果超過(guò)就刪除該連接,并判斷當(dāng)前連接池內(nèi)總的連接數(shù)是否小于minConn(最小連接數(shù)),若小于就將連接池充滿;如果沒超過(guò)就將該連接標(biāo)記為開放狀態(tài),可供再次復(fù)用??梢钥闯稣沁@套策略保證了數(shù)據(jù)庫(kù)連接的有效復(fù)用,避免頻繁地建立、釋放連接所帶來(lái)的系統(tǒng)資源開銷。⑶連接池的配置數(shù)據(jù)庫(kù)連接池中到底要放置多少個(gè)連接,才能使系統(tǒng)的性能更佳,用minConn和maxConn來(lái)限制。minConn是當(dāng)應(yīng)用啟動(dòng)的時(shí)候連接池所創(chuàng)建的連接數(shù),如果過(guò)大啟動(dòng)將變慢,但是啟動(dòng)后響應(yīng)更快;如果過(guò)小啟動(dòng)加快,但是最初使用的用戶將因?yàn)檫B接池中沒有足夠的連接不可避免的延緩了執(zhí)行速度。因此應(yīng)該在開發(fā)的過(guò)程中設(shè)定較小minConn,而在實(shí)際應(yīng)用的中設(shè)定較大minConn。maxConn是連接池中的最大連接數(shù),可以通過(guò)反復(fù)試驗(yàn)來(lái)確定此飽和點(diǎn)。為此在連接池類ConnectionPool中加入兩個(gè)方法getActiveSize()和getOpenSize(),ActiveSize

表示某一時(shí)間有多少連接正被使用,OpenSize表示連接池中有多少連接被打開,反映了連接池使用的峰值。將這兩個(gè)值在日志信息中反應(yīng)出來(lái),minConn的值應(yīng)該小于平均ActiveSize,而maxConn的值應(yīng)該在activeSize和OpenSize之間。⑷連接池的關(guān)鍵技術(shù)①事務(wù)處理

前面討論的是關(guān)于使用數(shù)據(jù)庫(kù)連接進(jìn)行普通的數(shù)據(jù)庫(kù)訪問。對(duì)于事務(wù)處理,情況就變得比較復(fù)雜。因?yàn)槭聞?wù)本身要求原則性的保證,此時(shí)就要求對(duì)于數(shù)據(jù)庫(kù)的操作符合"All-All-Nothing"原則,即要么全部完成,要么什么都不做。如果簡(jiǎn)單的采用上述的連接復(fù)用的策略,就會(huì)發(fā)生問題,因?yàn)闆]有辦法控制屬于同一個(gè)事務(wù)的多個(gè)數(shù)據(jù)庫(kù)操作方法的動(dòng)作,可能這些數(shù)據(jù)庫(kù)操作是在多個(gè)連接上進(jìn)行的,并且這些連接可能被其他非事務(wù)方法復(fù)用。Connection本身具有提供了對(duì)于事務(wù)的支持,可以通過(guò)設(shè)置Connection的AutoCommit屬性為false,顯式的調(diào)用commit或rollback方法來(lái)實(shí)現(xiàn)。但是要安全、高效的進(jìn)行連接復(fù)用,就必須提供相應(yīng)的事務(wù)支持機(jī)制。方法是:采用顯式的事務(wù)支撐方法,每一個(gè)事務(wù)獨(dú)占一個(gè)連接。這種方法可以大大降低對(duì)于事務(wù)處理的復(fù)雜性,并且又不會(huì)妨礙連接的復(fù)用。連接管理服務(wù)提供了顯式的事務(wù)開始、結(jié)束(commit或rollback)聲明,以及一個(gè)事務(wù)注冊(cè)表,用于登記事務(wù)發(fā)起者和事務(wù)使用的連接的對(duì)應(yīng)關(guān)系,通過(guò)該表,使用事務(wù)的部分和連接管理部分就隔離開,因?yàn)樵摫硎窃谶\(yùn)行時(shí)根據(jù)實(shí)際的調(diào)用情況動(dòng)態(tài)生成的。事務(wù)使用的連接在該事務(wù)運(yùn)行中不能被復(fù)用。在實(shí)現(xiàn)中,用戶標(biāo)識(shí)是通過(guò)使用者所在的線程來(lái)標(biāo)識(shí)的。后面的所有對(duì)于數(shù)據(jù)庫(kù)的訪問都是通過(guò)查找該注冊(cè)表,使用已經(jīng)分配的連接來(lái)完成的。當(dāng)事務(wù)結(jié)束時(shí),從注冊(cè)表中刪除相應(yīng)表項(xiàng)。②并發(fā)為了使連接管理服務(wù)有更大的通用性,我們必須要考慮到多線程環(huán)境,即并發(fā)問題。在一個(gè)多線程的環(huán)境下,必須要保證連接管理自身數(shù)據(jù)的一致性和連接內(nèi)部數(shù)據(jù)的一致性,在這方面Java提供很好的支持(synchronized關(guān)鍵字),這樣就很容易使連接管理成為線程安全的。③多數(shù)據(jù)庫(kù)服務(wù)器在實(shí)際應(yīng)用中,應(yīng)用程序常常需要訪問多個(gè)不同的數(shù)據(jù)庫(kù)。如何通過(guò)同一個(gè)連接池訪問不同的數(shù)據(jù)庫(kù),是應(yīng)用程序需要解決的一個(gè)核心問題⑸連接池應(yīng)用的實(shí)現(xiàn)一個(gè)完整的連接池應(yīng)用包括三個(gè)部分:DBConnectionPool類,負(fù)責(zé)從連接池獲取(或創(chuàng)建)連接、將連接返回給連接池、系統(tǒng)關(guān)閉時(shí)關(guān)閉所有連接釋放所有資源;DBConnectionManager類,負(fù)責(zé)裝載和注冊(cè)JDBC驅(qū)動(dòng)、根據(jù)屬性文件中定義的屬性創(chuàng)建DBConnectionPool、跟蹤應(yīng)用程序?qū)B接池的引用等;應(yīng)用程序?qū)B接池的使用。本文實(shí)現(xiàn)的數(shù)據(jù)庫(kù)連接池包括一個(gè)管理類DBConnectionManager,負(fù)責(zé)提供與多個(gè)連接池對(duì)象(DBConnectionPool類)之間的接口。每一個(gè)連接池對(duì)象管理一組封裝過(guò)的JDBC連接對(duì)象Conn,封裝過(guò)的JDBC連接對(duì)象Conn可以被任意數(shù)量的Model層的組件共享。類Conn

的設(shè)計(jì)很簡(jiǎn)單,如下所示:

ClassConn{

Privatejava.sgl.Connectioncon;//數(shù)據(jù)庫(kù)連接對(duì)象

PublicBooleaninUse;//是否被使用

PubliclonglastAccess;//最近一次釋放該連接的時(shí)間

Publicint

useCount;//被使用次數(shù)

}下面是實(shí)現(xiàn)連接池的主要代碼:

//初始化數(shù)據(jù)庫(kù)連接池

publicstaticsynchronizedvoidFastInitPool()

throwsException{

try{Class.forName(driver);

for(inti=0;i<size;i++){

Connectioncon=createConnection();

if(con!=null)addConnection(con);

}}}

//向連接池對(duì)象中添加數(shù)據(jù)庫(kù)連接

privatestaticvoidaddConnection(Connectioncon){

if(pool=null||pool1=null){

pool=newVector(size);

pool1=newVector(size);}

pool.addElement(con);

pool1.addElement("false");}

//獲取數(shù)據(jù)庫(kù)連接

publicstaticsynchronizedConnectiongetConn()

throwsException{

Connectionconn=null;

try{if(driver=null)

FastInitPool();

//獲得一個(gè)可用的(空閑的)連接

.for(inti=0;i<pool.size();i++){

conn=(Connection)pool.elementAt(i);

if(pool1.elementAt(i)=="false"){

pool1.set(i,"true");

//System.out.println("從連接池中獲取第"+(i+1)+"個(gè)空閑連接");

returnconn;

}

}

//如果沒有可用連接,且已有連接數(shù)小于最大連接數(shù)限制,則創(chuàng)建并增加一個(gè)新連接到連接池

conn=createConnection();

pool.addElement(conn);

pool1.addElement("true");

//System.out.println("所有連接都在使用,在連接池中再創(chuàng)建一個(gè)新連接");

}

catch(Exceptione){

System.err.println(e.g

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論