日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

JDBC技術(shù)和數(shù)據(jù)庫連接池專題

 duduwolf 2006-05-03
JDBC基礎(chǔ)知識

一、采用JDBC訪問數(shù)據(jù)庫的基本步驟:
    A.載入JDBC驅(qū)動程序
    B.定義連接URL
    C.建立連接
    D.創(chuàng)建Statement對象
    E.執(zhí)行查詢或更新
    F.結(jié)果處理
    G.關(guān)閉連接

二、載入JDBC驅(qū)動程序:
1.為了使代碼盡可能地靈活,我們要避免對類名的引用進(jìn)行硬編碼(hard-coding),因此我們可以采用從Properties文件中載入驅(qū)動程序的方法,也可以使用在服務(wù)器中配置數(shù)據(jù)源(DataSource)的方法來避免在代碼中硬編碼
    
2.在開發(fā)過程中要保證CLASSPATH設(shè)定中包括驅(qū)動程序JAR文件所在的路徑。在WEB服務(wù)
器上部署時(shí)要將JAR文件放在Web應(yīng)用的WEB-INF/lib目錄下。如果多個(gè)Web應(yīng)用使用相同的數(shù)據(jù)庫驅(qū)動程序可以將JAR文件放置在服務(wù)器使用的公共目錄<%CATALINA_HOME%>\common\lib中

三、定義連接URL:
       載入JDBC驅(qū)動程序之后,必須指定數(shù)據(jù)庫服務(wù)器位置。指向數(shù)據(jù)庫的URL所使用的協(xié)議是:
    jdbc:子協(xié)議,并且載入服務(wù)器的主機(jī)名、端口、數(shù)據(jù)庫名(或引用)。如:Oracle 的連接URL: 
    jdbc:oracle:thin:@192.168.0.71:1521:UMV2
    jdbc:oracle:采用Oracle驅(qū)動程序
    thin:指連接服務(wù)器所采用的模式
    @192.168.0.71:服務(wù)器的地址
    1521:服務(wù)器的監(jiān)聽端口
    UMV2:數(shù)據(jù)庫名

四、建立連接:
    1.一個(gè)數(shù)據(jù)庫連接(Connection)可以通過其自身的getMetaData()來獲取它的自身信息
    2.默認(rèn)情況下一個(gè)數(shù)據(jù)庫的連接是自動提交模式的(auto-commit),也就是說每當(dāng)一個(gè)SQL語句
被執(zhí)行后其改變結(jié)果都會被自動提交,如果auto-commit模式被關(guān)閉,那么方法commit()必須被顯式調(diào)用以提交改變結(jié)果,否則的話所有對數(shù)據(jù)庫操作的結(jié)果都不會被保存

五、創(chuàng)建Statement對象:
在同一時(shí)間下,每個(gè)Statement對象只能打開一個(gè)ResultSet對象。所以,假如有兩個(gè)同樣結(jié)果的結(jié)果集在交叉訪問,那么這兩個(gè)結(jié)果集必定為兩個(gè)不同的Statement對象所創(chuàng)建。如果在打開一個(gè)新的結(jié)果集的時(shí)候存在一個(gè)已經(jīng)打開的結(jié)果集,則這個(gè)已經(jīng)存在的結(jié)果集會被隱式的關(guān)閉    

六、執(zhí)行查詢或更新:
    在Statement對象中可以執(zhí)行如下的操作:
    A.查詢操作:executeQuery(SQL語句)  B.維護(hù)操作:executeUpdate(SQL語句)
    C.批處理操作:executeBath()

七、結(jié)果處理:
    1.ResultSet中行的第一列索引為1,而非0,訪問ResultSet中的數(shù)據(jù)時(shí)要使用列名,而非索引
     但要注意使用列名作為查詢條件是大小寫敏感的。

    2.JDBC1.0中,我們只能在ResultSet中向前移動;在JDBC2.0中,我們可以在ResultSet中向
     下(next)或向上(previous)移動,同樣也可以移到特定的行(relative,absolute)

3.默認(rèn)情況下ResultSet是不可更新的,且只能向前移動。下面的代碼顯示了如何創(chuàng)建一個(gè)可滾動的、對更新敏感的ResultSet

       Statement stmt = con.createStatement(
                                      ResultSet.TYPE_SCROLL_INSENSITIVE,
                                      ResultSet.CONCUR_UPDATABLE);
       ResultSet rs = stmt.executeQuery("SELECT a, b FROM TABLE2");
       // rs will be scrollable, will not show changes made by others,
       // and will be updatable
      
    4.ResultSet和ResultSetMetaData沒有直接提供方法返回查詢所返回的行數(shù)。然而,在JDBC
     2.0中,可以通過調(diào)用last()方法將游標(biāo)定位到ResultSet的最后一行,然后調(diào)用getRow()方
     法獲取當(dāng)前的行號。在JDBC1.0中,確定行數(shù)的惟一方式是重復(fù)調(diào)用ResultSet的next()方法,
     直到它返回false為至

八、關(guān)閉連接:
    在關(guān)閉數(shù)據(jù)庫連接時(shí)應(yīng)該以ResultSet、Statement、Connection的順序進(jìn)行

JDBC-PreparedStatement(預(yù)備語句)

一、PreparedStatement(預(yù)備語句)的創(chuàng)建:
首先按照標(biāo)準(zhǔn)的格式創(chuàng)建參數(shù)化語句,在實(shí)際使用之前發(fā)送參數(shù)到數(shù)據(jù)庫進(jìn)行編譯。用問號表示語句中應(yīng)該為具體的值所替換的位置。每次使用預(yù)備語句時(shí),只需要使用相應(yīng)的setXxx調(diào)用,替換語句中標(biāo)記出來的參數(shù)。然后就可以和常規(guī)的語句一樣,使用executeQuery或execute/executeUpdate修改表中的數(shù)據(jù)。例如:

Connection connection = DriverManager.getConnection (url,username,password);
// 創(chuàng)建帶問號的參數(shù)化語句
String template = " UPDATE music SET price=? WHERE id=? ";
PreparedStatement statement = connection.prepareStatement (template);

float newPrices[] = getNewPrices();
int recordingIDs = getIDs();
for(int i=0; i<recordingIDs.length;i++){
   // 用setXxx代替?
   statement.setFloat(1,newPrices[i]);
   statement.setInt(2,recordingIDs[i]);
   // 執(zhí)行預(yù)備語句
statement.execute();}

二、使用PreparedStatement的好處:
1.依賴于服務(wù)器對預(yù)編譯查詢的支持,以及驅(qū)動程序處理原始查詢的效率,預(yù)備語句在性能上的優(yōu)勢可能有很大的不同。
2.安全是預(yù)備語句的另外一個(gè)特點(diǎn),我們推薦在通過HTML表單接受用戶輸入,然后對數(shù)據(jù)庫進(jìn)行更新時(shí),一定要使用預(yù)備語句或存儲過程。
3.預(yù)備語句還能夠正確地處理嵌入在字符串中的引號以及處理非字符數(shù)據(jù)(比如向數(shù)據(jù)庫發(fā)送序列化后的對象)    

JDBC-CallableStatement(可調(diào)用語句)

一、使用CallableStatement(可調(diào)用語句)的優(yōu)缺點(diǎn):
1.優(yōu)點(diǎn):語法錯(cuò)誤可以在編譯時(shí)找出來,而非在運(yùn)行期間;數(shù)據(jù)庫存儲過程的運(yùn)行可能比常規(guī)的
SQL查詢快得多;程序員只需知道輸入和輸出參數(shù),不需了解表的結(jié)構(gòu)。另外,由于數(shù)據(jù)庫語言能夠訪問數(shù)據(jù)庫本地的一下兒功能(序列,觸發(fā)器,多重游標(biāo)),因此用它來編寫存儲過程可能要比使用Java編程語言要簡易一些。
2.缺點(diǎn):存儲過程的商業(yè)邏輯在數(shù)據(jù)庫服務(wù)器上運(yùn)行,而非客戶機(jī)或Web服務(wù)器。而行業(yè)的發(fā)展趨勢是盡可能多地將商業(yè)邏輯移出數(shù)據(jù)庫,將它們放在JavaBean組件(或者在大型的系統(tǒng)中,EnterPrise JavaBean組件)中,在Web構(gòu)架上采用這種方式的主要?jiǎng)訖C(jī)是:數(shù)據(jù)庫訪問和網(wǎng)絡(luò)I/O常常是性能的瓶頸。

二、使用CallableStatement在JAVA中調(diào)用數(shù)據(jù)庫存儲過程:

1.定義對數(shù)據(jù)庫過程的調(diào)用
    A.無參數(shù)過程:{ call procedure_name}
     B. 僅有輸入?yún)?shù)的過程:{call procedure_name(?,?...)}
    C.有一個(gè)輸出參數(shù)的過程:{? Call procedure_name}
    D.既有輸入?yún)?shù)又有輸出參數(shù)的過程{?=call procedure_name(?,?...)}
  在過程的4種形式中要注意過程可能返回多個(gè)輸出參數(shù),并且參數(shù)的索引值從輸出參數(shù)開始。因此前面最后例子中,第一個(gè)輸入?yún)?shù)的索引值是2而不是1。
2.為過程準(zhǔn)備CallableStatement
  String procedure = “{ ? = call procedure_name(?,?) }”;
  CallableStatement statement = connection.prepareCall(procedure);
3.提供輸入?yún)?shù)的值
  在執(zhí)行存儲過程之前,我們需要調(diào)用與所要設(shè)置的項(xiàng)以及參數(shù)的類型相對應(yīng)的setXxx,替換標(biāo)記出來的輸入?yún)?shù)
  Statement.setString(2,”name”);
4.注冊輸出參數(shù)的類型
    我們必須使用registerOutParameter注冊每個(gè)輸出參數(shù)的JDBC類型
  Statement.registerOutParameter(n,type);
5.執(zhí)行這個(gè)存儲過程
  Statement.execute();
6.訪問返回的輸出參數(shù)
  可以通過調(diào)用getXxx訪問每個(gè)對應(yīng)的輸出參數(shù)



例如:
Connection connection = DriverManager.getConnection(url,username,password);
String procedure = “{ ? = call myProc(?,?)}”;
CallableStatement statement = connection.prepareCall(procedure);
statement.setString(2,×××);
statement.setFloat(3,×××);
statement.registerOutParameter(1,Types.INTEGER);
statement.execute();
int row = statement.getInt(1);

JDBC-Transation(事務(wù)處理)

一、Transation(事務(wù)處理)的概念:
在更新數(shù)據(jù)庫時(shí),默認(rèn)情況下,更改是永久性寫入到數(shù)據(jù)庫。然而這種默認(rèn)行為可以通過編寫程序來關(guān)閉。在自動交付關(guān)閉的情況下,如果在更新時(shí)發(fā)生問題,則對數(shù)據(jù)庫的每個(gè)更改都能夠取消(或者說回退到最初的值)。如果更新成功,那么之后可以將這些更改永久性提交給數(shù)據(jù)庫。這種方式也稱為事務(wù)管理。
我們需要確保,要么所有的操作都發(fā)生,要么所有的操作都不發(fā)生。這就是事務(wù)管理的原則。

二、在JAVA中使用Transation(事務(wù)管理)保證數(shù)據(jù)庫的完整性:
我們使用try-catch-finally塊來正確地應(yīng)對事務(wù)管理,首先,記錄自動提交的當(dāng)前狀態(tài)。然后,在try塊中,調(diào)用setAutoCommit(false)并執(zhí)行一系列的查詢或更新。如果發(fā)生故障,則在catch塊中調(diào)用rollback;如果事務(wù)成功,則在try塊的結(jié)尾調(diào)用commit。不管哪種方式,都在finally塊中重置自動提交的狀態(tài)。例如:

Connection connection = DriverManager.getConnection(url,username,password);
boolean autoCommit = connection.getAutoCommit();
Statement statement;
try{
    connection.setAutoCommit(false);    // 關(guān)閉數(shù)據(jù)庫的自動提交
    statement = connection.createStatement();
statement.execute(…);
statement.execute(..);

connection.commit();                // 如果所有語句執(zhí)行成功則提交事務(wù)
}
catch(SQLException sqle){
    connection.rollback();                // 如果有異常發(fā)生則回滾所有的事務(wù)
}
finally{
    if(statement!=null){statement.close();}
connection.setAutoCommit(autoCommit);    // 重置自動提交的狀態(tài)
}
上面的代碼中,從DriverManager獲取連接的語句在try/catch塊之外。這樣除非成功獲取連接,否則不會調(diào)用rollback。如果把獲取連接的語句放在try/catch快之內(nèi),一旦在連接成功后發(fā)生異常,由于rollback的作用會把已經(jīng)建立的連接斷開。但是getConnection方法也會拋出SQLException異常這個(gè)異常要么被外圍的方法重新拋出,要么在單獨(dú)的try/catch塊內(nèi)捕獲。 
JDBC的常用API

一、Connection接口:
    1.createStatement():創(chuàng)建數(shù)據(jù)庫連接
    2.prepareStatement(String sql):創(chuàng)建預(yù)處理語句
    3.prepareCall(String sql):創(chuàng)建可調(diào)用語句

    4.getAutoCommit():獲取自動提交的模式
    5.setAutoCommit():設(shè)置自動提交的模式
    
    6.commit():提交所執(zhí)行的SQL語句
    7.rollback():回滾所執(zhí)行的SQL語句

    8.getMetaData():獲取一個(gè)DatabaseMetaData對象,該對象包含了有關(guān)數(shù)據(jù)庫的基本信息

    9.close():關(guān)閉數(shù)據(jù)庫連接
    10.isClose():判斷數(shù)據(jù)庫連接是否超時(shí)或被顯示關(guān)閉

二、Statement接口:
    1.execute(String sql):執(zhí)行SQL語句,如果返回值是結(jié)果集則為true,否則為false
    2.executeQuery(String sql):執(zhí)行SQL語句,返回值為ResultSet
    3.executeUpdate(String sql):執(zhí)行SQL語句,返回值為所影響的行數(shù)
    
    4.addBatch(String sql):向當(dāng)前Statement對象的命令列表中添加新的批處理SQL語句
    5.clearBatch():清空當(dāng)前Statement對象的命令列表
    6.executeBatch():執(zhí)行當(dāng)前Statement對象的批處理語句,返回值為每個(gè)語句所影響的函數(shù)數(shù)組

    7.getConnection():返回創(chuàng)建了該Statement對象的Connection對象

    8.getQueryTimeout():獲取等待處理結(jié)果的時(shí)間
    9.setQueryTimeout():設(shè)置等待處理結(jié)果的時(shí)間
          
三、ResultSet接口:    
    1.first()/beforeFirst():將游標(biāo)移動到ResultSet中第一條記錄(的前面)
    2.last()/afterLast():將游標(biāo)移動到ResultSet中最后一條記錄(的后面)

    3.absolute(int column):將游標(biāo)移動到相對于第一行的指定行,負(fù)數(shù)則為相對于最后一條記錄
    4.relative(int rows):將游標(biāo)移動到相對于當(dāng)前行的第幾行,正為向下,負(fù)為向上

    5.next():將游標(biāo)下移一行
    6.previous():將游標(biāo)上移一行

    7.insertRow():向當(dāng)前ResultSet和數(shù)據(jù)庫中被插入行處插入一條記錄
    8.deleteRow():將當(dāng)前ResultSet中的當(dāng)前行和數(shù)據(jù)庫中對應(yīng)的記錄刪除
    9.updateRow():用當(dāng)前ResultSet中已更新的記錄更新數(shù)據(jù)庫中對應(yīng)的記錄
    10.cancelUpdate():取消當(dāng)前對ResultSet和數(shù)據(jù)庫中所做的操作

    11.findColumn(String columnName):返回當(dāng)前ResultSet中與指定列名對應(yīng)的索引

    12.getRow():返回ResultSet中的當(dāng)前行號

    13.refreshRow():更新當(dāng)前ResultSet中的所有記錄

    14.getMetaData():返回描述ResultSet的ResultSetMetaData對象

    15.isAfterLast(): 是否到了結(jié)尾
    16.isBeforeFirst(): 是否到了開頭
    17.isFirst():是否第一條記錄   
    18.isLast(): 是否最后一條記錄

    19.wasNull():檢查列值是否為NULL值,如果列的類型為基本類型,且數(shù)據(jù)庫中的值為0,那么
這項(xiàng)檢查就很重要。由于數(shù)據(jù)庫NULL也返回0,所以0值和數(shù)據(jù)庫的NULL不能區(qū)分。如果列的類型為對象,可以簡單地將返回值與null比較
    
20.close():關(guān)閉當(dāng)前ResultSet

四、ResultSetMetaData接口:
    1.getColumnCount():返回ResultSet中列的數(shù)目
    2.getColumnName():返回列在數(shù)據(jù)庫中的名稱
    3.getColumnType():返回列的SQL類型

    4.isReadOnly():表示該數(shù)據(jù)項(xiàng)是否為只讀值
    5.isNullable():表示該列是否可以存儲NULL



基于JDBC的數(shù)據(jù)庫連接池技術(shù)研究與應(yīng)用
  
Java應(yīng)用程序訪問數(shù)據(jù)庫的基本原理 

在Java語言中,JDBC(Java DataBase Connection)是應(yīng)用程序與數(shù)據(jù)庫溝通的橋梁, 即Java語言通過JDBC技術(shù)訪問數(shù)據(jù)庫。JDBC是一種“開放”的方案,它為數(shù)據(jù)庫應(yīng)用開發(fā)人員、數(shù)據(jù)庫前臺工具開發(fā)人員提供了一種標(biāo)準(zhǔn)的應(yīng)用程序設(shè)計(jì)接口,使開發(fā)人員可以用純Java語言編寫完整的數(shù)據(jù)庫應(yīng)用程序。JDBC提供兩種API,分別是面向開發(fā)人員的API和面向底層的JDBC驅(qū)動程序API,底層主要通過直接的JDBC驅(qū)動和JDBC-ODBC橋驅(qū)動實(shí)現(xiàn)與數(shù)據(jù)庫的連接。 

一般來說,Java應(yīng)用程序訪問數(shù)據(jù)庫的過程(如圖1所示)是: 
?、傺b載數(shù)據(jù)庫驅(qū)動程序; 
?、谕ㄟ^JDBC建立數(shù)據(jù)庫連接; 
 ③訪問數(shù)據(jù)庫,執(zhí)行SQL語句; 
?、軘嚅_數(shù)據(jù)庫連接。 
 
JDBC作為一種數(shù)據(jù)庫訪問技術(shù),具有簡單易用的優(yōu)點(diǎn)。但使用這種模式進(jìn)行Web應(yīng)用程序開發(fā),存在很多問題:首先,每一次Web請求都要建立一次數(shù)據(jù)庫連接。建立連接是一個(gè)費(fèi)時(shí)的活動,每次都得花費(fèi)0.05s~1s的時(shí)間,而且系統(tǒng)還要分配內(nèi)存資源。這個(gè)時(shí)間對于一次或幾次數(shù)據(jù)庫操作,或許感覺不出系統(tǒng)有多大的開銷??墒菍τ诂F(xiàn)在的Web應(yīng)用,尤其是大型電子商務(wù)網(wǎng)站,同時(shí)有幾百人甚至幾千人在線是很正常的事。在這種情況下,頻繁的進(jìn)行數(shù)據(jù)庫連接操作勢必占用很多的系統(tǒng)資源,網(wǎng)站的響應(yīng)速度必定下降,嚴(yán)重的甚至?xí)斐煞?wù)器的崩潰。不是危言聳聽,這就是制約某些電子商務(wù)網(wǎng)站發(fā)展的技術(shù)瓶頸問題。其次,對于每一次數(shù)據(jù)庫連接,使用完后都得斷開。否則,如果程序出現(xiàn)異常而未能關(guān)閉,將會導(dǎo)致數(shù)據(jù)庫系統(tǒng)中的內(nèi)存泄漏,最終將不得不重啟數(shù)據(jù)庫。還有,這種開發(fā)不能控制被創(chuàng)建的連接對象數(shù),系統(tǒng)資源會被毫無顧及的分配出去,如連接過多,也可能導(dǎo)致內(nèi)存泄漏,服務(wù)器崩潰。 

數(shù)據(jù)庫連接池(connection pool)的工作原理 

1、基本概念及原理 

數(shù)據(jù)庫連接池的基本思想就是為數(shù)據(jù)庫連接建立一個(gè)“緩沖池”。預(yù)先在緩沖池中放入一定數(shù)量的連接,當(dāng)需要建立數(shù)據(jù)庫連接時(shí),只需從“緩沖池”中取出一個(gè),使用完畢之后再放回去。我們可以通過設(shè)定連接池最大連接數(shù)來防止系統(tǒng)無盡的與數(shù)據(jù)庫連接。更為重要的是我們可以通過連接池的管理機(jī)制監(jiān)視數(shù)據(jù)庫的連接的數(shù)量、使用情況,為系統(tǒng)開發(fā)、測試及性能調(diào)整提供依據(jù)。 

2、服務(wù)器自帶的連接池 

JDBC的API中沒有提供連接池的方法。一些大型的WEB應(yīng)用服務(wù)器如BEA的WebLogic和IBM的WebSphere等提供了連接池的機(jī)制,但是必須有其第三方的專用類方法支持連接池的用法。 

連接池關(guān)鍵問題分析 

1、并發(fā)問題 

為了使連接管理服務(wù)具有最大的通用性,必須考慮多線程環(huán)境,即并發(fā)問題。這個(gè)問題相對比較好解決,因?yàn)镴ava語言自身提供了對并發(fā)管理的支持,使用synchronized關(guān)鍵字即可確保線程是同步的。使用方法為直接在類方法前面加上synchronized關(guān)鍵字,如: 
public synchronized Connection getConnection()  

2、多數(shù)據(jù)庫服務(wù)器和多用戶 

對于大型的企業(yè)級應(yīng)用,常常需要同時(shí)連接不同的數(shù)據(jù)庫(如連接Oracle和Sybase)。如何連接不同的數(shù)據(jù)庫呢?我們采用的策略是:設(shè)計(jì)一個(gè)符合單例模式的連接池管理類,在連接池管理類的唯一實(shí)例被創(chuàng)建時(shí)讀取一個(gè)資源文件,其中資源文件中存放著多個(gè)數(shù)據(jù)庫的url地址(<poolName.url>)、用戶名(<poolName.user>)、密碼(<poolName.password>)等信息。如tx.url=172.21.15.123:5000/tx_it,tx.user=yang,tx.password=yang321。根據(jù)資源文件提供的信息,創(chuàng)建多個(gè)連接池類的實(shí)例,每一個(gè)實(shí)例都是一個(gè)特定數(shù)據(jù)庫的連接池。連接池管理類實(shí)例為每個(gè)連接池實(shí)例取一個(gè)名字,通過不同的名字來管理不同的連接池。 

對于同一個(gè)數(shù)據(jù)庫有多個(gè)用戶使用不同的名稱和密碼訪問的情況,也可以通過資源文件處理,即在資源文件中設(shè)置多個(gè)具有相同url地址,但具有不同用戶名和密碼的數(shù)據(jù)庫連接信息。 

3、事務(wù)處理 

我們知道,事務(wù)具有原子性,此時(shí)要求對數(shù)據(jù)庫的操作符合“ALL-ALL-NOTHING”原則,即對于一組SQL語句要么全做,要么全不做。 

在Java語言中,Connection類本身提供了對事務(wù)的支持,可以通過設(shè)置Connection的AutoCommit屬性為false,然后顯式的調(diào)用commit或rollback方法來實(shí)現(xiàn)。但要高效的進(jìn)行Connection復(fù)用,就必須提供相應(yīng)的事務(wù)支持機(jī)制??刹捎妹恳粋€(gè)事務(wù)獨(dú)占一個(gè)連接來實(shí)現(xiàn),這種方法可以大大降低事務(wù)管理的復(fù)雜性。 

4、連接池的分配與釋放 

連接池的分配與釋放,對系統(tǒng)的性能有很大的影響。合理的分配與釋放,可以提高連接的復(fù)用度,從而降低建立新連接的開銷,同時(shí)還可以加快用戶的訪問速度。 

對于連接的管理可使用空閑池。即把已經(jīng)創(chuàng)建但尚未分配出去的連接按創(chuàng)建時(shí)間存放到一個(gè)空閑池中。每當(dāng)用戶請求一個(gè)連接時(shí),系統(tǒng)首先檢查空閑池內(nèi)有沒有空閑連接。如果有就把建立時(shí)間最長(通過容器的順序存放實(shí)現(xiàn))的那個(gè)連接分配給他(實(shí)際是先做連接是否有效的判斷,如果可用就分配給用戶,如不可用就把這個(gè)連接從空閑池刪掉,重新檢測空閑池是否還有連接);如果沒有則檢查當(dāng)前所開連接池是否達(dá)到連接池所允許的最大連接數(shù)(maxConn),如果沒有達(dá)到,就新建一個(gè)連接,如果已經(jīng)達(dá)到,就等待一定的時(shí)間(timeout)。如果在等待的時(shí)間內(nèi)有連接被釋放出來就可以把這個(gè)連接分配給等待的用戶,如果等待時(shí)間超過預(yù)定時(shí)間timeout,則返回空值(null)。系統(tǒng)對已經(jīng)分配出去正在使用的連接只做計(jì)數(shù),當(dāng)使用完后再返還給空閑池。對于空閑連接的狀態(tài),可開辟專門的線程定時(shí)檢測,這樣會花費(fèi)一定的系統(tǒng)開銷,但可以保證較快的響應(yīng)速度。也可采取不開辟專門線程,只是在分配前檢測的方法。 

5、連接池的配置與維護(hù) 

連接池中到底應(yīng)該放置多少連接,才能使系統(tǒng)的性能最佳?系統(tǒng)可采取設(shè)置最小連接數(shù)(minConn)和最大連接數(shù)(maxConn)來控制連接池中的連接。最小連接數(shù)是系統(tǒng)啟動時(shí)連接池所創(chuàng)建的連接數(shù)。如果創(chuàng)建過多,則系統(tǒng)啟動就慢,但創(chuàng)建后系統(tǒng)的響應(yīng)速度會很快;如果創(chuàng)建過少,則系統(tǒng)啟動的很快,響應(yīng)起來卻慢。
可以在開發(fā)時(shí),設(shè)置較小的最小連接數(shù),開發(fā)起來會快,而在系統(tǒng)實(shí)際使用時(shí)設(shè)置較大的,因?yàn)檫@樣對訪問客戶來說速度會快些。最大連接數(shù)是連接池中允許連接的最大數(shù)目,具體設(shè)置多少,要看系統(tǒng)的訪問量,可通過反復(fù)測試,找到最佳點(diǎn)。 

如何確保連接池中的最小連接數(shù)呢?有動態(tài)和靜態(tài)兩種策略。動態(tài)即每隔一定時(shí)間就對連接池進(jìn)行檢測,如果發(fā)現(xiàn)連接數(shù)量小于最小連接數(shù),則補(bǔ)充相應(yīng)數(shù)量的新連接,以保證連接池的正常運(yùn)轉(zhuǎn)。靜態(tài)是發(fā)現(xiàn)空閑連接不夠時(shí)再去檢查。 

連接池的實(shí)現(xiàn) 

1、連接池模型 

連接池類是對某一數(shù)據(jù)庫所有連接的“緩沖池”,主要實(shí)現(xiàn)以下功能:①從連接池獲取或創(chuàng)建可用連接;②使用完畢之后,把連接返還給連接池;③在系統(tǒng)關(guān)閉前,斷開所有連接并釋放連接占用的系統(tǒng)資源;④還能夠處理無效連接(原來登記為可用的連接,由于某種原因不再可用,如超時(shí),通訊問題),并能夠限制連接池中的連接總數(shù)不低于某個(gè)預(yù)定值和不超過某個(gè)預(yù)定值。 

連接池管理類是連接池類的外覆類(wrapper),符合單例模式,即系統(tǒng)中只能有一個(gè)連接池管理類的實(shí)例。其主要用于對多個(gè)連接池對象的管理,具有以下功能:①裝載并注冊特定數(shù)據(jù)庫的JDBC驅(qū)動程序;②根據(jù)屬性文件給定的信息,創(chuàng)建連接池對象;③為方便管理多個(gè)連接池對象,為每一個(gè)連接池對象取一個(gè)名字,實(shí)現(xiàn)連接池名字與其實(shí)例之間的映射;④跟蹤客戶使用連接情況,以便需要是關(guān)閉連接釋放資源。連接池管理類的引入主要是為了方便對多個(gè)連接池的使用和管理,如系統(tǒng)需要連接不同的數(shù)據(jù)庫,或連接相同的數(shù)據(jù)庫但由于安全性問題,需要不同的用戶使用不同的名稱和密碼。 

2、連接池實(shí)現(xiàn) 

下面給出連接池類和連接池管理類的主要屬性及所要實(shí)現(xiàn)的基本接口: 

public class DBConnectionPool implements TimerListener{ 

private int checkedOut;//已被分配出去的連接數(shù) 
private ArrayList freeConnections = new ArrayList();//容器,空閑池,根據(jù)創(chuàng)建時(shí)間順序存放已創(chuàng)建
尚未分配出去的連接 
private int minConn;//連接池里連接的最小數(shù)量 
private int maxConn;//連接池里允許存在的最大連接數(shù) 
private String name;//為這個(gè)連接池取個(gè)名字,方便管理 
private String password;//連接數(shù)據(jù)庫時(shí)需要的密碼 
private String url;//所要?jiǎng)?chuàng)建連接的數(shù)據(jù)庫的地址 
private String user;//連接數(shù)據(jù)庫時(shí)需要的用戶名 
public Timer timer;//定時(shí)器 

public DBConnectionPool(String name, String URL, String user, Stringpassword, int maxConn) 
public synchronized void freeConnection(Connection con) //使用完畢之后把連接返還給空閑池 
public synchronized Connection getConnection(long timeout)//得到一個(gè)連接,timeout是等待時(shí)間 
public synchronized void release()//斷開所有連接,釋放占用的系統(tǒng)資源 
private Connection newConnection()//新建一個(gè)數(shù)據(jù)庫連接 
public synchronized void TimerEvent() //定時(shí)器事件處理函數(shù) 
}

public class DBConnectionManager { 

static private DBConnectionManager instance;//連接池管理類的唯一實(shí)例 
static private int clients;//客戶數(shù)量 
private ArrayList drivers = new ArrayList();//容器,存放數(shù)據(jù)庫驅(qū)動程序 
private HashMap pools = new HashMap ();//以name/value的形式存取連接池對象的名字及連接池對象 

private void loadDrivers(Properties props)//裝載數(shù)據(jù)庫驅(qū)動程序 
private void createPools(Properties props)//根據(jù)屬性文件提供的信息,創(chuàng)建一個(gè)或多個(gè)連接池 

private DBConnectionManager()//私有構(gòu)造函數(shù),在其中調(diào)用初始化函數(shù)init() 
private void init()//初始化連接池管理類的唯一實(shí)例,由私有構(gòu)造函數(shù)調(diào)用 
static synchronized public DBConnectionManager getInstance()//如果唯一的實(shí)例instance已經(jīng)創(chuàng)建,直接返回這個(gè)實(shí)例;否則,調(diào)用私有構(gòu)造函數(shù),創(chuàng)建連接池管理類的唯一實(shí)例 

public Connection getConnection(String name)//從名字為name的連接池對象//中得到一個(gè)連接 
public Connection getConnection(String name, long time)//從名字為name 的連接池對象中取得一個(gè)連接,time是等待時(shí)間 

public void freeConnection(String name, Connection con)//釋放一個(gè)連接name是一個(gè)連接池對象的名 
public synchronized void release()//釋放所有資源 

}   

3、連接池使用 

上面所實(shí)現(xiàn)的連接池在程序開發(fā)時(shí)如何應(yīng)用到系統(tǒng)中呢?下面以Servlet為例說明連接池的使用。 
Servlet的生命周期是:在開始建立servlet時(shí),調(diào)用其初始化(init)方法。之后每個(gè)用戶請求都導(dǎo)致一個(gè)調(diào)用前面建立的實(shí)例的service方法的線程。最后,當(dāng)服務(wù)器決定卸載一個(gè)servlet時(shí),它首先調(diào)用該servlet的 destroy方法。 根據(jù)servlet的特點(diǎn),我們可以在初始化函數(shù)中生成連接池管理類的唯一實(shí)例(其中包括創(chuàng)建一個(gè)或多個(gè)連接池)。如: 

public void init() throws ServletException 

  // getInstance()?DBConnectionManager()?init()
 connMgr = DBConnectionManager.getInstance();  
}   

然后就可以在service方法中通過連接池名稱使用連接池,執(zhí)行數(shù)據(jù)庫操作。最后在destroy方法中釋放占用的系統(tǒng)資源,如:  

public void destroy() {  
connMgr.release(); 
super.destroy();  
}

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多